Performance tracing is an essential process that involves the collection, analysis and interpretation of system data. The primary objective of performance tracing is to identify bottlenecks, diagnose problems and optimize performance to ensure that systems operate within their limits.
The following example serves as an introduction to the broader concept of performance tracing only. There are various technologies available to facilitate performance tracing and selecting the right one is critical.
To demonstrate how performance tracing can be implemented using an extended Berkeley Packet Filter (eBPF), we will measure the startup time of containers. eBPF is a Linux kernel technology that allows developers to insert custom code into the kernel to trace and analyze system events. Using this mechanism, developers can collect detailed performance data on system components—even containerized applications—without needing external monitoring tools or profilers.
We recently published how Podman's performance is important to the automotive industry—which uses a fork/exec model to create new containers. Measuring the startup time of a container in eBPF is done by following the dependency graph of parent processes and their children back to the initial Podman command executed in its own process. This logic is implemented in fork_exec_snoop.bt. In the bpftrace file, a high-level tracing language is used to interact with the Linux BPF system.
The logic in this eBPF program is split into two parts:
- The first part of the program waits for the first execution of a Podman command, which acts as a trigger by setting the value of the global variable
@time_normalized
to the current time. - The second part of the program is invoked as soon as
@time_normalized
is initialized and it prints information about syscalls:sys_enter_clone
,syscalls:sys_exit_clone
,syscalls:sys_enter_exec*
andsyscalls:sys_exit_exec*
events.
The output of the fork_exec_snoop.bt
eBPF program looks similar to this:
Attaching 9 probes... TRACEPOINT T DT PID PPID TGID PTGID CMD syscalls:sys_exit_exec* 0 1507 39324 38662 39324 38662 podman syscalls:sys_enter_clone 40544 39326 38662 39324 38662 podman <redacted>
The details show the time between syscalls:sys_exit_clone
and syscalls:sys_enter_exec*
. This includes the time it takes for the kernel to perform various tasks associated with the syscalls:sys_enter_exec*
system call, such as:
- Loading the new executable into memory
- Setting up the process' address space
- Initializing the stack and heap
- Loading shared libraries
- Starting the new program's execution
The duration can vary depending on several factors, including the size and complexity of the new executable, the amount of shared libraries to load and the system's overall load and resources. This information is helpful when optimizing the performance of Podman in general.
For developers who want to measure the performance on their systems, there are two additional valuable metrics that can be derived from the output.
The first one is the time Podman requires to start the container's process command, true
. This is the timestamp of the syscalls:sys_exit_exec*
event before syscalls:sys_enter_exec*
with the true
command. In this case, it takes Podman roughly 0.16 seconds to start the container’s process command. This time largely depends on the specifications of the system being tested. Running Podman for the first time after a reboot always takes significantly more time than subsequent runs in which the caches are already populated.
TRACEPOINT T DT PID PPID TGID PTGID CMD syscalls:sys_exit_exec* 163698 899 39368 39326 39368 39324 3
The second important piece of information is related to the application in the container itself. The time between syscalls:sys_enter_exec*
and syscalls:sys_exit_exec*
measures the execution time of the program. In this case, it took 1107 microseconds, or about 0.001 seconds, to run the true command.
TRACEPOINT T DT PID PPID TGID PTGID CMD syscalls:sys_exit_exec* 168723 1107 39367 39362 39367 39362 true
To run this performance analysis yourself, replicate the process on Fedora, Red Hat Enterprise Linux or any equivalent operating system.
Download the container image used in this demo, as well as the eBPF program:
podman pull quay.io/fedora/fedora:latest curl -X GET https://raw.githubusercontent.com/containers/podman/main/hack/fork_exec_snoop.bt -o fork_exec_snoop.bt chmod +x fork_exec_snoop.bt
Run the eBPF program:
# first terminal ./fork_exec_snoop.bt > fork_exec.log
The eBPF program will now wait for a Podman command in a forked process.
NOTE: Make sure that no other process is calling Podman during the measurement, because it might pollute the log output even though it would not tamper the results.
In a second terminal, run Podman:
# second terminal podman run --pull=never --network=host --security-opt seccomp=unconfined quay.io/fedora/fedora:latest true
After the Podman command has returned, press Ctrl+C to stop the tracing in the first terminal and inspect the log:
less fork_exec.log
Although this is meant to be an introduction into eBPF for developers who want to tweak container performance, there are many other potential use cases for using eBPF. For developers of container images and other systems with fast startup requirements, it is worth examining the outcomes of this measurement in detail to improve the performance of the system.
About the authors
Paul Wallrabe, a former consultant, boasts expertise in Kubernetes-backend development and the elimination of toil through automation in developer toolchains. With a solid background in the automotive industry, he has turned his attention to the unique challenges that this sector presents to Linux.
Pierre-Yves Chibon (aka pingou) is a Principal Software Engineer who spent nearly 15 years in the Fedora community and is now looking at the challenges the automotive industry offers to the FOSS ecosystems.
Browse by channel
Automation
The latest on IT automation for tech, teams, and environments
Artificial intelligence
Updates on the platforms that free customers to run AI workloads anywhere
Open hybrid cloud
Explore how we build a more flexible future with hybrid cloud
Security
The latest on how we reduce risks across environments and technologies
Edge computing
Updates on the platforms that simplify operations at the edge
Infrastructure
The latest on the world’s leading enterprise Linux platform
Applications
Inside our solutions to the toughest application challenges
Original shows
Entertaining stories from the makers and leaders in enterprise tech
Products
- Red Hat Enterprise Linux
- Red Hat OpenShift
- Red Hat Ansible Automation Platform
- Cloud services
- See all products
Tools
- Training and certification
- My account
- Customer support
- Developer resources
- Find a partner
- Red Hat Ecosystem Catalog
- Red Hat value calculator
- Documentation
Try, buy, & sell
Communicate
About Red Hat
We’re the world’s leading provider of enterprise open source solutions—including Linux, cloud, container, and Kubernetes. We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.
Select a language
Red Hat legal and privacy links
- About Red Hat
- Jobs
- Events
- Locations
- Contact Red Hat
- Red Hat Blog
- Diversity, equity, and inclusion
- Cool Stuff Store
- Red Hat Summit