Manual dynamic analysis
When is manual dynamic analysis relevant?
Though beLow allows you to run dynamic analysis automatically, this is not always possible, depending on your use case.
Automated dynamic analysis will not be possible if:
You are running your application in an environment unable to print data to a file (usage of
fprintfnot possible)Running your application is not scriptable (e.g., requires clicking in some Windows software, requires human interaction, etc)
In this context, there are two possibilities:
Running static analysis only: beLow will still be able to find some optimizations, but their impact will certainly be under or over-evaluated. An optimization in an initialization function and an optimization in a deep for-loop would have the same weight, while in runtime reality, the first one would be executed once and the second one million times.
Running manual dynamic analysis: in this case, we provide you an instrumented code that you manually have to build, run, and retrieve data from.
Manual dynamic analysis is not suitable in fully automated environments like CI/CD, but it is recommended when you want accurate insights about what beLow can improve in your code.
How to run a manual dynamic analysis?
When setting up a project without automated dynamic analysis, before running analysis, you get a card prompting either to run static analysis or to use manual dynamic analysis.
Before analysis
At this point, you have 2 choices:
Run a static analysis by clicking Run analysis, or
Perform a manual dynamic analysis
The steps to run a manual dynamic analysis are:
Download instrumented code
Click the corresponding button in the UI to download instrumented-code.zip. Unzip it. The archive contains:
main.c: the instrumented code. Ideally do not modify this file.below_vendor.i: beLow vendor generated code (not supposed to be modified).below_instr.i: beLow customizable code which you should modify as needed.
Merge the unzipped code into your original project (or a copy). The instrumented code adds counters to measure execution frequency of code blocks and formats data for export.
Merge and optionally adapt instrumented code
Merge the instrumented files into your project. You may:
Apply the instrumented files directly to the original project (you can revert later with git), or
Work in a copy of your project.
Default behavior implemented by the instrumented code:
Allocates a global array of counters
Increments counters (one index per instrumented block)
Prints counters as text into a file named
wedolow.profwhen the program exits
Modify below_instr.i if your environment requires different behavior (for example, sending profile output over UART on a microcontroller).
In the next section we walk through a full example.
Example project
The example project is a single-file C program that sums two random integer vectors every 1 second in an endless loop.
main.c
Build command used in the example:
Download instrumented code
After unzipping, merge the instrumented files into the project as described above.
The instrumented main.c contains calls to BELOW_COUNT(id) and an include of below_instr.i, for example:
main.c (instrumented)
The file below_instr.i contains the custom logic for counters:
below_instr.i
Key elements inside below_instr.i:
Counters array and type:
Modify the type depending on your platform and expected maximum counter values.
Initialization function called on first count (or via atexit):
Custom count function called on each instrumented point:
Finish function that writes
wedolow.profby default:
below_vendor.i (vendor code) defines, among other things, the preprocessor variable:
You may use BELOW_DYNAMIC_ANALYSIS in your original code to alter behavior only in dynamic analysis mode. For example, the original infinite loop can be limited to a fixed number of iterations in dynamic analysis mode to allow the instrumented run to end and produce profiling output.
Example: original main modified for dynamic analysis to stop after 10 iterations
main.c (modified)
The corresponding instrumented version includes the same BELOW_COUNT calls; when built with the dynamic-analysis-aware original code, the instrumented run will terminate after 10 iterations.
Build and run the instrumented example:
When the instrumented execution stops, wedolow.prof is created. Example content:
wedolow.prof
The first number (16) is the number of counters (BELOW_N_COUNTERS).
Following numbers are the counter values recorded during the run.
Upload the wedolow.prof file via the beLow UI and click Run analysis. The analysis will incorporate the execution data.
Adapting manual dynamic analysis to your usage
For any project, the instrumented package contains:
A modified version of your project files (content depends on the project)
below_vendor.i(stable vendor content)below_instr.i(customizable)
All custom logic (counters allocation, initialization, termination) is in below_instr.i. In most cases you only need to modify this file and keep a copy in your project so you don't rewrite changes for each manual analysis.
Ensure your instrumented execution ends at some point. Use BELOW_DYNAMIC_ANALYSIS in your original code if needed to limit runtime.
Examples of custom modifications (illustrative of use cases present in the original content):
On microcontrollers, initialize UART and write profiling data to UART instead of a file, then copy-paste output into
wedolow.prof.If you have debug tools accessing program memory, read the counters array directly and format the data offline.
In both cases, modifying below_instr.i should be sufficient.
Upload profiling data
Once uploaded, click Run analysis. The analysis will use your profiling information.
Last updated 3 months ago
