Measuring performance with the perf kernel tool

Inside Job

Author(s):

The kernel supports performance analysis with built-in tools via the Linux performance counters subsystem. perf is easy to use and offers a detailed view of performance data.

Making systems faster is a core part of business. Optimizing resources in data centers can save energy, space, and costs, and, out in the real world, a faster start-up time can improve the user experience for an entertainment system in the living room or even a car in the driveway.

In complex systems with many components, performance problems can stem from many different causes. On the hardware side, the CPU, RAM, the bus load, the memory system (block I/O), or the network can contribute to performance issues. On the software side, the operating system, the execution environment of the programming language, libraries, or the application itself can create bottlenecks. The fact that these components also often influence each other makes things more difficult. Although the systems work without any problems on their own, their interaction leads to friction.

To identify the root cause in the interaction of all these components requires the observer to take a bird's eye view and also have detailed knowledge of all the components. Not many IT professionals combine these skills, thus making performance optimization an exciting but challenging activity.

Fortunately, several useful tools are available for monitoring performance issues, including well-known utilities such as ps, stat, top, htop, OProfile [1], SystemTap [2], and so on.

One of the most useful performance monitoring tools is perf [3], which has been part of the kernel since version 2.6.31. perf uses the kernel's performance counter subsystem and supports both profiling and tracing.

During profiling, Perf evaluates data from hardware registers that count specific hardware events. Thus, it generates statistics at certain times in order to gain an impression of the system. The accuracy depends on the frequency of measurement.

In tracing, however, perf logs certain events using trace points. These include software events such as context changes, but also hardware events such as executed instructions, cache requests, and so on. System messages are also included.

Admins and developers should keep in mind that tracing can have a major influence on the system. In general, you need to take into account that the measurements themselves can influence the measurement results.

Installation

The perf program is part of the Linux kernel and located in the tools/perf directory. As the output from make tools/help shows, you can install with make -C perf_install. You can also simply change the directory to /usr/src/<Linux_version>/tools/perf and execute make there.

Because certain perf functions depend on the Linux application binary interface (ABI), distributions often ship one package per kernel version. Under Ubuntu 18.10, the linux-tools-generic package always installs the appropriate perf version.

If you want meaningful output, you also need to install the debug symbols for the programs you wish to example – just as you would with a debugger. The debug symbols are usually stored in separate archives. The packages automatically generated on Debian and Ubuntu 18.10 have an extension of -dbgsym, and the manually generated packages have an extension of -dbg.

Workflow

perf supports more than two dozen subcommands. For an overview, type the command without any parameters or check out the perf wiki [4]. People who use perf usually start with perf list. This command displays the available events (Listing 1), which you can then count with perf stat. The record command writes data to the hard disk; report displays the data for searching. script supports further evaluation of the data at the end.

Listing 1

Outputting Hardware Events (excerpt)

01 $ sudo perf list hardware
02
03 List of pre-defined events (to be used in -e):
04
05 branch-instructions OR branches [Hardware event]
06 branch-misses [Hardware event]
07 bus-cycles [Hardware event]
08 cache-misses [Hardware event]
09 [...]

Events

The Admin perf list command also gives an optional argument on request (refer to Listing 1). This argument may be the type of the event, for example hw or tracepoint, or a regular expression, as in Listing 2.

Listing 2

Events at Block Level (excerpt)

01 $ sudo perf list 'block:*'
02
03 List of pre-defined events (to be used in -e):
04
05 block:block_bio_backmerge [Tracepoint event]
06 block:block_bio_bounce [Tracepoint event]
07 block:block_bio_complete [Tracepoint event]
08 block:block_bio_frontmerge [Tracepoint event]
09 block:block_bio_queue [Tracepoint event]
10 [...]

Each end of line contains the event type in square brackets. In addition, you normally have to look into the source code to see the exact meaning of the event. You can use the --events or -e switch to state the events to be considered.

top on Steroids

You can create a performance counter profile in real time with perf top (Figure 1). The overview is similar to that of top, but you can jump directly to the individual events.

Figure 1: The console browser of perf top --sort=comm,dso on an Intel Kaby Lake system with Ubuntu 18.10 and Gnome 3.30.1.

perf stat counts the events of the entire system until you abort by pressing Ctrl+C, or the specified command terminates. Listing 3 shows the subcommand in action; it lists two events for the factor command.

Listing 3

Output from perf stat

01 $ sudo perf stat -e branches -e branch-misses factor 120808125801214124898080833
02 120808125801214124898080833: 13 29 911 7589 21089 77471 28369829
03
04 Performance counter stats for 'factor 120808125801214124898080833':
05
06 191,242 branches
07 10,332 branch-misses # 5.40% of all branches
08
09 0.000649438 seconds time elapsed
10
11 0.000699000 seconds user
12 0.000000000000 seconds sys

Data Recorder

The perf record command can generate a performance counter profile for a specific command. If you want an overview of the entire system, or if the process to be examined is unknown, simply add the sleep command:

sudo perf record -ag sleep 5

This line creates the default perf.data file in the current directory. The -a switch ensures that perf considers all CPUs, and -g generates a call graph. -i lets you feed a file to perf record.

The perf report command evaluates the stored data and uses the perf.data file. As with perf top, the command presents an overview. After pressing Enter, you also see details for the functions.

By the way, the --sort= comm,dso switch (see Figure 1) provides a better overview. Figure 2 shows the output for an Intel Kaby Lake system with Gnome 3.30.1 playing a movie in Firefox 63.0.3. The figure shows that the CPU and not the GPU is used for decoding.

Figure 2: Perf measures the performance of the default browser with perf report --sort=comm,dso.

Event-Driven

If only certain events are of interest, the -e switch can help. Listing 4 shows the output on a system with Rsync running.

Listing 4

Track Events

01 $ sudo perf report --stdio
02 [...]
03 # Samples: 1K of event 'block:block_rq_issue'
04 # Event count (approx.): 1741
05 #
06 # Children Self Command Shared Object Symbol
07 # ........  ....  ...........  ................  ....................
08 #
09 93.74% 93.74% rsync kernel.kallsyms] [k] blk_peek_request
10 |
11 |--89.20%-- __lxstat64
12 | blk_peek_request
13 |
14 |--3.45%-- __GI___mkdir
15 | blk_peek_request
16 |
17 |--0.63%-- 0x646c6975622f3930
18 | __GI___link
19 | blk_peek_request
20 |
21 -0.46%-- 0x6d492f636f642f65
22 __GI___link
23 blk_peek_request
24
25 89.20% 0.00% rsync libc-2.27.so [.] __lxstat64
26 |
27 ---__lxstat64
28 blk_peek_request
29 [...]

--stdio tells perf to display the overview in plain text directly on the console. The recorded event was a request to the kernel block layer. The command line was:

sudo perf record -e block:block_rq_issue -ag

On Fire

perf can also even create pretty graphics. Thanks to flame graphs, admins and developers can determine the most frequently used software paths. The developer tools integrated into browsers can also generate graphics (Figure 3).

Figure 3: Browser-based developer tools also offer performance analysis features.

The x-axis shows the load of the individual processes; the y-axis the resolution of each function call. The wider the blocks, the more resources their processes require, which helps you see which areas are problematic are most in need of optimizing.

Admins can also generate flame graphs from perf data. You do not have to write the script yourself – look for the script on GitHub [5]:

git clone https://github.com/brendangregg/FlameGraph

The commands from Listing 5 record the performance data and create a flame graph with perf script (Figure 4). The flame graph shows that, although the browser is playing a 720p video, the kernel is pretty much in sleep mode. In the browser, individual sections of the flame graph can be zoomed in and out.

Listing 5

Commands for Creating a Flame Graph

01 sudo perf record -F 99 -a -g -- sleep 10
02 sudo perf script > out.perf
03 ./stackcollapse-perf.pl out.perf > out.folded
04 ./flamegraph.pl out.folded > out.svg
05 firefox out.svg
Figure 4: A script-generated flame graph of the perf data. If desired, you can zoom in or out at the push of a button.

Dynamic Tracing

Using the perf probe subcommand and the --add switch, admins can define dynamic trace points. Listing 6 shows the procedure using the Linux tcp_sendmsg() function as an example.

Listing 6

tcp_sendmsg as Dynamic Trace Point

01 $ sudo perf probe --addd='tcp_sendmsg'
02 Added new event:
03 probe:tcp_sendmsg (on tcp_sendmsg)
04 [...]
05 $ sudo perf record -e probe:tcp_sendmsg -aR sleep 5
06 [ perf record: Woken up 1 times to write data ]
07 $ sudo perf report --stdio
08 [...]

Dynamic Duo

The Linux perf subsystem and the perf tool collection offer many possibilities for analyzing a system. Admins can easily collect and evaluate data with existing tools and scripts to achieve an overview. Correct interpretation of the data requires some knowledge of the perf subsystem. Because the Linux kernel delivers perf directly, you won't need to worry about installing external modules.

Reading Matter

You will quickly find numerous resources for perf on the web. First and foremost certainly are Brendan Gregg's [6] pages; Gregg worked on DTrace at Sun and now uses perf intensively at Netflix in his work as a performance engineer. His book System Performance [7] is regarded as one of the standard works in this field.

Many admins and developers have discovered that better knowledge of perf leads to faster problem analysis. Some development environments also include perf, and a few training providers offer perf training. It seems clear that performance optimization will continue to play an important role in system administration in the future. BPFtrace (see box "BPFtrace," [8]) might be the next exciting project in the pipeline.

BPFtrace

Early in the fall of 2018, Alastair Robertson published the high-level BPFtrace [8] language, which runs in the eBPF VM of the Linux kernel. This allows the kernel to start certain operations, such as filter processes, directly in kernel space, which avoids the need for context switching between kernel and user space and thus puts significantly less strain on the system.