Optimize a sample C++ application on an Arm-based server with Arm Performix
Introduction
Set up Arm Performix
Build a sample C++ dot-product application
Find code hotspots in the scalar dot-product application
Identify CPU pipeline bottlenecks in the scalar dot-product application
Examine instruction patterns in the scalar dot-product application
Optimize the dot-product application with Arm Neon intrinsics
Validate the optimized dot-product application
Next Steps
Optimize a sample C++ application on an Arm-based server with Arm Performix
Introduction
Set up Arm Performix
Build a sample C++ dot-product application
Find code hotspots in the scalar dot-product application
Identify CPU pipeline bottlenecks in the scalar dot-product application
Examine instruction patterns in the scalar dot-product application
Optimize the dot-product application with Arm Neon intrinsics
Validate the optimized dot-product application
Next Steps
Run the Code Hotspots recipe
The Code Hotspots recipe in Arm Performix identifies which functions in your application consume the most CPU time. This analysis helps identify areas of code that can benefit from optimization.
To run the recipe:
In Performix, select the Code Hotspots recipe from the list of available recipes.
Selecting the Code Hotspots recipeSpecify the path to your compiled binary and any necessary parameters. Performix assumes the home directory as the base path, so use the relative path from
$HOME. For this example, run the program with 16M floats and an iteration count of 2000 to ensure sufficient runtime for meaningful sampling:performix-analysis/dot_scalar 16777216 2000Arm recommends collecting at least 20 seconds of profiling data to ensure statistically meaningful sampling. Adjust the iteration count if needed for your hardware.
Select Run Recipe to start the analysis. Performix launches the program on the target and collects periodic samples during execution.
Interpret the results
After the run completes, Performix displays the results, including a flame graph that highlights where the CPU spends most of its time. Each box represents a function, and its width indicates how frequently it appears in the samples. The stacked layout shows call paths, helping you see how each function is reached.
You can identify optimization opportunities by focusing on the widest blocks, which represent the most significant contributors to runtime.
The dot_scalar function dominates the flame graph, indicating it accounts for a large proportion of total CPU cycles.
Code Hotspots flame graph
The Insights panel shows the sample count. This function accounts for 99.47% of samples.
Switch to the Call Stack view to see how the hotspot function is reached and whether its cost comes from the function itself or its callees.
Call Stack view
Double-click the hotspot function to open the Source Code Viewer and inspect the exact lines of code associated with high CPU usage. When you open the Source Code Viewer for the first time, you need to specify the root directory of your source code so Performix can map profiling data to the correct files.
The Source Code Viewer runs on your local machine. To view annotated source on Performix, copy scalar_dot_product.cpp from the target to your local machine:
scp username@your-server:~/performix-analysis/scalar_dot_product.cpp .
Source code viewer for dot_scalar
What you’ve accomplished and what’s next
You identified the dot_scalar function as the dominant hotspot in the application. This is expected because it handles all the computation, but knowing it’s hot doesn’t tell you whether the time is being spent efficiently.
Next, you’ll use the CPU Microarchitecture recipe to understand why this function is a bottleneck.