Skip to content

Commit 4b898bc

Browse files
committed
final tech review of hotspots LP
1 parent c40c35f commit 4b898bc

6 files changed

Lines changed: 29 additions & 17 deletions

File tree

content/learning-paths/servers-and-cloud-computing/cpu_hotspot_performix/_index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
---
2-
title: Find CPU Cycle Hotspots with Arm Performix
2+
title: Find Code Hotspots with Arm Performix
33

44
draft: true
55
cascade:
66
draft: true
77

88
minutes_to_complete: 30
99

10-
who_is_this_for: Software developers and performance engineers who want to identify CPU cycle hotspots in applications running on Arm Linux systems.
10+
who_is_this_for: Software developers and performance engineers who want to identify code hotspots in applications running on Arm Linux systems.
1111

1212
learning_objectives:
13-
- Run the CPU Cycle Hotspot recipe in Arm Performix
13+
- Run the Code Hotspots recipe in Arm Performix
1414
- Identify which functions consume the most CPU cycles and target them for optimization
1515

1616
prerequisites:
240 KB
Loading
Binary file not shown.

content/learning-paths/servers-and-cloud-computing/cpu_hotspot_performix/how-to-1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ This Learning Path does not cover flame graphs in depth. To learn more, see [Bre
2626

2727
On Linux, flame graphs are commonly generated from samples collected with `perf`. perf periodically interrupts the running program and records a stack trace, then the collected stacks are converted into a folded format and rendered as the graph. Sampling frequency is important. If the frequency is too low you may miss short-lived hotspots, and if it is too high you may introduce overhead or skew the results. To make the output informative, compile with debug symbols and preserve frame pointers so stacks resolve to meaningful function names and unwind reliably. A typical build uses `-g` and `-fno-omit-frame-pointer`.
2828

29-
Arm has built a tool, Arm Performix that simplifies this workflow through the CPU Cycle hotspot recipe, making it easier to configure collection, run captures, and explore the resulting call hierarchies without manually stitching together the individual steps. This is the tooling solution you will use in this Learning Path.
29+
Arm has built a tool, Arm Performix that simplifies this workflow through the Code Hotspots recipe, making it easier to configure collection, run captures, and explore the resulting call hierarchies without manually stitching together the individual steps. This is the tooling solution you will use in this Learning Path.

content/learning-paths/servers-and-cloud-computing/cpu_hotspot_performix/how-to-3.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ weight: 4
66
layout: learningpathall
77
---
88

9-
## Run CPU Cycle Hotspot Recipe
9+
## Run Code Hotspots Recipe
1010

11-
As shown in the `main.cpp` file below, the program generates a 1920×1080 bitmap image of the fractal. To identify performance bottlenecks, run the CPU Cycle Hotspot recipe in Arm Performix (APX). APX uses sampling to estimate where the CPU spends most of its time, allowing it to highlight the hottest functions—especially useful in larger applications where it isn't obvious ahead of time which functions will dominate runtime.
11+
As shown in the `main.cpp` file below, the program generates a 1920×1080 bitmap image of the fractal. To identify performance bottlenecks, run the Code Hotspots recipe in Arm Performix (APX). APX uses sampling to estimate where the CPU spends most of its time, allowing it to highlight the hottest functions—especially useful in larger applications where it isn't obvious ahead of time which functions will dominate runtime.
1212

1313
{{% notice Note %}}
14-
The `myplot.draw()` call uses a relative path (`./images/green.bmp`). When APX launches the binary, it runs it from `/tmp/atperf/tools/atperf-agent`, so the image would be written there rather than to your project directory. Replace the first string argument with the absolute path to your `images` folder (for example, `/home/ec2-user/Mandelbrot-Example/green.bmp`) and rebuild the application before continuing.
14+
The `myplot.draw()` call uses a relative path (`./images/green.bmp`). When APX launches the binary, it runs it from a temporary location, so the image would be written there rather than to your project directory. To ensure the output is saved where you expect it, update the first string argument in `main.cpp` to the absolute path of the output file, for example `/home/ec2-user/Mandelbrot-Example/images/green.bmp`.
1515
{{% /notice %}}
1616

1717
```cpp
@@ -23,35 +23,40 @@ using namespace std;
2323
int main(){
2424

2525
Mandelbrot::Mandelbrot myplot(1920, 1080);
26-
myplot.draw("./images/green.bmp", Mandelbrot::Mandelbrot::GREEN);
26+
myplot.draw("/home/ec2-user/Mandelbrot-Example/images/green.bmp", Mandelbrot::Mandelbrot::GREEN);
2727

2828
return 0;
2929
}
3030
```
31+
Rebuild the application before continuing:
3132

32-
Open APX from the host machine. Select the **CPU Cycle Hotspot** recipe. If this is the first time running the recipe on this target machine you may need to select the install tools button.
33+
```bash
34+
./build.sh
35+
```
3336

34-
![The Arm Performix recipe selection screen with the CPU Cycle Hotspot recipe highlighted#center](./install-tools.jpg "Selecting the CPU Cycle Hotspot recipe")
37+
Open APX from the host machine. Select the **Code Hotspot** recipe. If this is the first time running the recipe on this target machine you may need to select the install tools button.
38+
39+
![The Arm Performix recipe selection screen with the Code Hotspots recipe highlighted#center](./install-tools.jpg "Selecting the Code Hotspots recipe")
3540

3641
Configure the recipe to launch a new process. APX will automatically start collecting metrics when the program starts and stop when the program exits.
3742

3843
Provide the absolute path to the binary built in the previous step: `/home/ec2-user/Mandelbrot-Example/builds/mandelbrot`.
3944

4045
Use the default sampling rate of **Normal**. If your application is short-running, consider a higher sample rate, at the cost of more data to store and process.
4146

42-
![The Arm Performix CPU Cycle Hotspot recipe configuration screen showing launch settings, binary path, and sampling rate fields#center](./hotspot-config.jpg "CPU Cycle Hotspot recipe configuration")
47+
![The Arm Performix Code Hotspots recipe configuration screen showing launch settings, binary path, and sampling rate fields#center](./code-hotspots-config.png "Code Hotspots recipe configuration")
4348

4449
## Analyse Results
4550

4651
A flame graph is generated once the run completes. The default colour mode labels the hottest functions—those using CPU most frequently—in the darkest shade. In this example, the `__complex_abs__` function is present in approximately 65% of samples, and it calls the `__hypot` symbol in `libm.so`.
4752

4853
![A flame graph showing single-threaded Mandelbrot profiling results with __complex_abs__ as the dominant hotspot#center](./single-thread-flame-graph.jpg "Single-threaded flame graph showing __complex_abs__ as the hottest function")
4954

50-
To investigate further, you can map source code lines to the functions in the flame graph. Right-click on a specific function and select **View Source Code**. At the time of writing (ATP Engine 0.44.0), you may need to copy the source code onto your host machine.
55+
To investigate further, you can map source code lines to the functions in the flame graph. Right-click on a specific function and select **View Source Code**. You may need to copy the source code onto your host machine to use this feature.
5156

5257
![The Arm Performix flame graph view showing source code annotations mapped to the selected hot function#center](./view-with-source-code.jpg "Flame graph with source code view")
5358

54-
Finally, check your `images` directory for the generated bitmap fractal.
59+
Finally, check your `images` directory for the generated bitmap fractal `green.bmp`
5560

5661
![A rendered Mandelbrot set fractal in green, generated from the single-threaded build at maximum iterations#center](./plot-1-thread-max-iterations.jpg "Mandelbrot fractal output from single-threaded build")
5762

content/learning-paths/servers-and-cloud-computing/cpu_hotspot_performix/how-to-4.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public:
3333
...
3434
```
3535

36-
On the remote server, reduce `MAX_ITERATIONS` in `Mandelbrot.h` to `(1<<9)` (512), update the output filename in `main.cpp` to a different path so you can compare the output with the baseline image, then rebuild:
36+
On the remote server, reduce `MAX_ITERATIONS` in `Mandelbrot.h` to `(1<<9)` (512), update the output image filename in `main.cpp` to a different name (for example: `green-512.bmp`)so you can compare the output with the baseline image, then rebuild:
3737

3838
```bash
3939
./build.sh
@@ -49,13 +49,20 @@ There is negligible difference in perceived image quality when halving `MAX_ITER
4949

5050
The loop in `Mandelbrot::getIterations` has no loop-carried dependencies — each iteration's result is independent of any other. This means you can parallelize the hot function across multiple threads if your CPU has multiple cores.
5151

52-
The repository contains a parallel version in the `main` branch:
52+
The repository contains a parallel version in the `main` branch. First stash the changes you made locally, then switch to the `main` branch.
5353

5454
```bash
55+
git stash
5556
git checkout main
5657
```
5758

58-
This branch parallelizes the `Mandelbrot::draw` function, which is an earlier function in the call stack that eventually calls `__hypot`. Build the example. This creates a binary `./builds/mandelbrot-parallel` that takes a single numeric command-line argument to set the number of threads.
59+
This branch parallelizes the `Mandelbrot::draw` function, which is an earlier function in the call stack that eventually calls `__hypot`. Before building, update the `myplot.draw()` call in `main.cpp` to use an absolute output path:
60+
61+
```cpp
62+
myplot.draw("/home/ec2-user/Mandelbrot-Example/images/Green-Parallel-512.bmp", Mandelbrot::Mandelbrot::GREEN);
63+
```
64+
65+
Build the example. This creates a binary `./builds/mandelbrot-parallel` that takes a single numeric command-line argument to set the number of threads.
5966

6067
```bash
6168
./build.sh
@@ -84,6 +91,6 @@ The build script uses the `-O0` flag, which disables all compiler optimizations.
8491

8592
In this Learning Path, you reduced the runtime of the Mandelbrot example by focusing on the hottest code paths—cutting execution time from around 1 minute to ~1 second through targeted optimization and parallelization. While this example is relatively simple and the optimizations are more obvious, the same principle applies to real-world workloads: optimize what matters most first, based on measurement.
8693

87-
The CPU Cycle Hotspot recipe is designed to quickly identify an application's most CPU-time-dominant functions, giving you a clear, evidence-based starting point for performance work. By surfacing where execution time is actually spent, it ensures your optimizations target the parts of the code most likely to deliver the largest gains.
94+
The Code Hotspots recipe is designed to quickly identify an application's most CPU-time-dominant functions, giving you a clear, evidence-based starting point for performance work. By surfacing where execution time is actually spent, it ensures your optimizations target the parts of the code most likely to deliver the largest gains.
8895

8996
This is often one of the first profiling steps to run when assessing an application's performance — especially to determine which functions dominate runtime and should be prioritized. Once hotspots are identified, you can follow up with deeper function-specific analysis, such as memory investigations or top-down studies, and build microbenchmarks around hot functions to explore lower-level bottlenecks and uncover additional optimization opportunities.

0 commit comments

Comments
 (0)