← Retour au blog
tech 29 July 2026

How to Profile eBPF Code?

Learn how to measure the performance impact of eBPF code with concrete examples and relevant tools.

Article inspired by the original source
How Do I Profile eBPF Code? ↗ naveensrinivasan.com

Introduction

eBPF (Extended Berkeley Packet Filter) has revolutionized how we interact with the Linux kernel. As a tech decision-maker or developer, understanding how to profile eBPF code is crucial to ensure your systems run optimally.

Why Profile eBPF Code?

eBPF allows executing code in the Linux kernel with enhanced security without modifying the kernel's source code. This offers great flexibility for monitoring, networking, and security. However, each code addition can potentially introduce overhead. It's essential to measure this impact to ensure the benefits outweigh the costs.

Setting Up the Test Environment

To illustrate how to profile eBPF code, let's take the example of measuring the performance of file open operations, one of the critical functions in an operating system. We use an eBPF hook to intercept file open calls and measure the overhead introduced.

Laying the Groundwork

First, we need a simple C program to test file opening. This program uses syscall(SYS_openat, …) instead of the libc wrapper to minimize interference. The goal is to measure file opening time under warm cache conditions, discarding the first 10% of results as a warmup period.

```c #define _GNU_SOURCE #include <fcntl.h> #include <stdio.h> #include <time.h> #include <stdint.h> #include <stdlib.h> #include <unistd.h> #include <sched.h> #include <sys/mman.h> #include <sys/syscall.h>

static inline uint64_t now_ns(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (uint64_t)ts.tv_sec * 1000000000ull + ts.tv_nsec; }

int main(int argc, char **argv) { const char path = argv[1]; uint64_t n = strtoull(argv[2], NULL, 10); uint64_t warm = n / 10; uint32_t d = mmap(NULL, n sizeof(uint32_t), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE, -1, 0); mlock(d, n sizeof(uint32_t)); for (uint64_t i = 0; i < n; i++) d[i] = 0; for (uint64_t i = 0; i < n; i++) { uint64_t t0 = now_ns(); long fd = syscall(SYS_openat, AT_FDCWD, path, O_RDONLY); uint64_t t1 = now_ns(); if (fd >= 0) close(fd); d[i] = (uint32_t)(t1 - t0); } for (uint64_t i = warm; i < n; i++) printf("%u\n", d[i]); return 0; } ```

Profiling with Perf and bpftool

To profile eBPF code, the perf tool is indispensable. It allows resolving symbols and analyzing where potential bottlenecks lie.

Configuration Commands

The following commands enable JIT and expose compiled symbols so perf can display them correctly:

``bash sudo sysctl -w net.core.bpf_jit_enable=1 sudo sysctl -w net.core.bpf_jit_kallsyms=1 ``

Then, run your eBPF code and use bpftool to check for symbol appearance:

``bash sudo bpftool prog show | rg -A4 ' lsm ' sudo rg 'bpf_prog_[0-9a-f]+_ '/proc/kallsyms | rg 'security|path|file|open' ``

Interpreting Results

Once data is collected, analyzing the results is crucial. Look for unusually high latencies and overhead patterns. This step will allow you to optimize your eBPF code and improve your system's overall performance.

Conclusion

Profiling eBPF code is essential to ensure minimal impact on system performance. With the right tools and a methodical approach, you can easily identify and mitigate potential bottlenecks.

Let's discuss your project in 15 minutes.

eBPF profiling performance Linux kernel system optimization
Deepthix newsletter · 100% AI · every Monday 8am

An AI agent reads tech for you.

Our AI agent scans ~200 sources per week and ships the best articles to your inbox Monday 8am. Free. One click to unsubscribe.

Visit the newsletter page →

Want to automate your operations?

Let's talk about your project in 15 minutes.

Book a call