{"id":51487619,"url":"https://github.com/tanelpoder/brr","last_synced_at":"2026-07-07T08:30:24.417Z","repository":{"id":365663558,"uuid":"1272011782","full_name":"tanelpoder/brr","owner":"tanelpoder","description":"eBPF Runtime Reporter and Profiler","archived":false,"fork":false,"pushed_at":"2026-06-18T09:14:46.000Z","size":4787,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-18T11:16:30.796Z","etag":null,"topics":["ebpf","linux","observability","performance"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tanelpoder.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-17T07:55:00.000Z","updated_at":"2026-06-18T11:15:12.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tanelpoder/brr","commit_stats":null,"previous_names":["tanelpoder/brr"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/tanelpoder/brr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanelpoder%2Fbrr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanelpoder%2Fbrr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanelpoder%2Fbrr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanelpoder%2Fbrr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tanelpoder","download_url":"https://codeload.github.com/tanelpoder/brr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tanelpoder%2Fbrr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35221308,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-07T02:00:07.222Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ebpf","linux","observability","performance"],"created_at":"2026-07-07T08:30:19.016Z","updated_at":"2026-07-07T08:30:24.408Z","avatar_url":"https://github.com/tanelpoder.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# eBPF Runtime Reporter and Profiler - brr\n\n**`brr`** is a Runtime Reporter and Profiler _for_ eBPF programs.\n\n![](docs/images/ebpf-lock-add-tsc-expanded.png)\n\nSince eBPF programs are pieces of machine code residing in (kernel) address space, you can profile them with standard `perf` just like any other kernel function. However, perf alone won't show you other useful metrics like number of executions and average eBPF program runtime, like [bpftop](https://github.com/jfernandez/bpftop) does. Also, I want an easy way to map CPU samples to original source code lines, where possible.\n\nI wanted to **unify** both approaches, display the bpftop-style call count \u0026 probe latency, with the ability to drill down into where _inside_ the eBPF program most of the time is spent. This tool is not calling the `perf` command under the hood, but uses `perf_event_open()` API directly. Also, it uses the `bpf()` syscall, for things like enabling eBPF program stats accounting (BPF\\_ENABLE\\_STATS) while `brr` is running. \n\nI built this for my own use, but this tool/idea may be useful for others too. It's entirely AI-coded by Codex in Python using my specs \u0026 tests. It's been good enough for my [performance testing](https://tanelpoder.com/posts/optimizing-ebpf-biolatency-accounting/) environments (but not so sure about production :-)\n\n1. [Jump to Installation section](#install)\n1. [Jump to command line options](#command-line-options)\n\n\n## Usage\n\n`brr` runs in two modes, **`brr top`** is an interactive TUI and other options like **`brr activity`**, **`brr profile`** produce profiles in plain text output (including JSON, CSV). See [EXAMPLE\\_OUTPUT.md](EXAMPLE_OUTPUT.md) for text mode profiling examples.\n\nHere are some screenshots from running `brr top` on a machine with some sysbench \u0026 fio stress-test workloads, while multiple different eBPF monitoring/observability programs were enabled.\n\nThe landing page shows the bpftop-style program execution summary. You can press \"h\" to display the help menu.\n\n![](docs/images/brr-top-entrypoint-trimmed.png)\n\nI had configured my `xcapture` tool to monitor all system calls of all threads in an efficient way (tracking + sampling, not tracing), we are apparently doing 2M syscalls/s on this machine and the `xcap_sys_enter` probe used 25% of _one CPU_ time in aggregate.\n\nNow you can use arrow keys to navigate to the program of interest and press enter to see its source code snippets (coming from each program's BTF info if available). \n\nI picked the `get_tasks` program as it's a longer and more complex program. It's an eBPF task iterator doing _passive sampling_ of all system threads' states, without injecting any tracepoints or probes into their critical path.\n\n![](docs/images/ebpf-task-local-storage.png)\n\nIn the image above, you see a column WEIGHT, this is just the number of perf CPU samples that fell into that specific code line.\n\nYou also see that some code lines have a little \"+\" sign in front of them. These are the CPU samples where we happened to be in some Linux _kernel_ function (not our eBPF program) - but that kernel function call was done by our eBPF program. You can press \"e\" to expand (and \"c\" to collapse) just like in perf to see the deeper stack under that eBPF program line.\n\nSo basically, I'm doing something like `perf record -g --call-graph ...` here, whenever I see a CPU sample in kernel function, I walk up the call-graph and see if the parent (or grandparent) function is our eBPF program of interest. eBPF programs can call (or fall) into Linux built-in kernel functions, as there are eBPF helper functions and other system activity like interrupts, page faults, spinlock gets, etc.\n\nHere's an example with a `lock_xadd()` function call immediately catching (my) eyes:\n\n![](docs/images/ebpf-lock-add-tsc-collapsed.png)\n\nBut when I expand the profile with \"e\", I see it's actually another function call `bpf_ktime_get_ns()` passed into the `lock_xadd(...)` as an argument that calls `read_tsc()` that takes most of the time under the original function call:\n\n![](docs/images/ebpf-lock-add-tsc-expanded.png)\n\nHere are two examples from the `syscount` command (part of bcc-tools) when running lots of syscalls concurrently:\n\n![](docs/images/ebpf-hashtable-collapsed.png)\n\nWhen expanded, we see that most of the samples fall under `__pi_memcpy` Linux kernel function:\n\n![](docs/images/ebpf-hashtable-expanded.png)\n\nWhen updating shared eBPF hash-maps under high concurrency (lots of events \u0026 lots of CPUs), then you might start seeing various \"lock\" functions showing up:\n\n![](docs/images/ebpf-hashtable-lock-bucket.png)\n\nWith modern eBPF _sleepable_ programs (that allow reading other processes memory), you might even start seeing kernel spin lock functions and page fault handlers showing up in your profiles:\n\n![](docs/images/ebpf-spinlock.png)\n\nYou can also press \"e\" on the folded/hidden lines showing `\"...\"` to expand the full source code (even without profile sample hits). Note that this source display is rendered from the actual binary representation, not the original source code file (compiler, JIT can move things around). So you may see weird source line ordering in the full program display.\n\n\n## Install\n\n### From Python source with uv\n\nRequires Linux, Python 3.11 or newer, and **uv** package manager. The install instructions for uv [are here](https://docs.astral.sh/uv/getting-started/installation/).\n\n```bash\ngit clone https://github.com/tanelpoder/brr.git\ncd brr\nuv sync\nsudo env PATH=\"$PATH\" uv run brr\n```\n\nTo build a self-contained single binary `brr` that you can run without `uv`:\n\n```bash\nuv tool install .\nsudo env PATH=\"$PATH\" brr\n```\n\nOnce you have the `brr` file, it's just like any other binary, you can copy and run it from any directory you like. The env tricks are not needed when you put the `brr` stand-alone binary to a directory that is in the PATH of sudo/root users (or just use fully qualified pathname when executing the program).\n\nWhen installing from a DEB/RPM package or putting the standalone binary into a directory that's in root-visible PATH, then you just run:\n\n```\nsudo brr\nsudo /usr/bin/brr\n```\n\n\n### Download Stand-alone binaries for ARM and X86\n\nIf you don't want to build from source and are happy to run binaries from random internet pages like this one, then you can download the latest standalone binary for your platform from the [releases](https://github.com/tanelpoder/brr/releases) page.\n\nOn x86:\n\n```\ncurl -L https://github.com/tanelpoder/brr/releases/download/v0.4.1/brr-0.4.1-linux-x86_64 -o brr\nchmod u+x brr\nsudo ./brr\n```\n\nOn ARM:\n\n```\ncurl -L https://github.com/tanelpoder/brr/releases/download/v0.4.1/brr-0.4.1-linux-aarch64 -o brr\nchmod u+x brr\nsudo ./brr\n```\n\n\n### Install Debian or Ubuntu Packages\n\nDownload the DEB for your architecture from the GitHub release, then install it:\n\n```bash\nsudo dpkg -i brr_0.4.1-1_amd64.deb\n```\n\nOn ARM64:\n\n```bash\nsudo dpkg -i brr_0.4.1-1_arm64.deb\n```\n\n### Install on Fedora, RHEL and RPM-compatible systems\n\nDownload the RPM for your architecture from the GitHub release, then install it:\n\n```bash\nsudo rpm -Uvh brr-0.4.1-1.x86_64.rpm\n```\n\nOn AArch64:\n\n```bash\nsudo rpm -Uvh brr-0.4.1-1.aarch64.rpm\n```\n\nThe packaged command installs as `/usr/bin/brr` and contains a standalone\nbinary. It does not depend on system Python.\n\n## Command line options\n\nMost useful commands need root or equivalent Linux capabilities because they\nopen BPF objects and CPU-wide perf events.\n\n\nThe `--help` option shows the key features and options at higher level. You can run `--help` also for subcommands to get more detail, like `brr top --help`.\n\n```\n$ sudo brr --help\nusage: brr [-h] [--bpffs BPFFS] [--json] [--csv] [--pretty] [-x] [-c] [-V]\n           {prog,activity,top,map,link,btf,perf-events,dump,dump-compare,profile} ...\n\neBPF Runtime Reporter and Profiler by Tanel Poder (tanelpoder.com).\n\npositional arguments:\n  {prog,activity,top,map,link,btf,perf-events,dump,dump-compare,profile}\n    prog                List loaded eBPF programs.\n    activity            Show eBPF program runtime deltas.\n    top                 Show the live eBPF top TUI.\n    map                 List loaded eBPF maps.\n    link                List loaded eBPF links.\n    btf                 List loaded BTF objects.\n    perf-events         List brr-supported perf events openable on this host.\n    dump                Dump translated instructions and source-line metadata for a program.\n    dump-compare        Compare brr dump output with bpftool source-line metadata.\n    profile             Profile BPF JIT execution with native perf_event_open sampling.\n\noptions:\n  -h, --help            show this help message and exit\n  --bpffs BPFFS         bpffs mount path used for pinned object enrichment.\n  --json                Emit machine-readable JSON instead of text.\n  --csv                 Emit machine-readable CSV instead of text.\n  --pretty              Pretty-print JSON output. Requires --json.\n  -x, --extended        Show extended TAG and PINNED columns in text output.\n  -c, --cumulative      Show cumulative runtime metrics where available in text output.\n  -V, --version         Show version number and exit.\n\n```\n\nOpen the interactive top-style TUI:\n\n```bash\nsudo brr top\nsudo brr top -x\nsudo brr top -c\n```\n\nInside `brr top`, press `x` to toggle extended columns and `c` to toggle\ncumulative columns.\n\nList loaded eBPF programs:\n\n```bash\nsudo brr\nsudo brr prog\nsudo brr -x\n```\n\nList other object types:\n\n```bash\nsudo brr map\nsudo brr link\nsudo brr btf\n```\n\nInclude runtime counters in the program list:\n\n```bash\nsudo brr prog --stats\n```\n\nShow runtime deltas:\n\n```bash\nsudo brr activity --duration 2 --limit 10\nsudo brr activity -x --duration 2\nsudo brr activity -c --duration 2\n```\n\nInspect a program by ID:\n\n```bash\nsudo brr dump 48\nsudo brr top --program-id 48\n```\n\nProfile BPF JIT CPU samples:\n\n```bash\nsudo brr profile --duration 5 --event auto\n```\n\nList perf events that `brr` can open on the current host:\n\n```bash\nsudo brr perf-events\n```\n\nIf `brr` is installed in a user-local path and you run it with `sudo`, preserve\nyour `PATH`:\n\n```bash\nsudo env PATH=\"$PATH\" brr\n```\n\n## Build Release Artifacts\n\nRelease artifacts are built locally from the current checkout. The standalone\nbinary is native to the build machine, so build on each target architecture.\n\n```bash\nuv sync --group dev --group package\nuv run --group package python scripts/build_release.py --all\n```\n\nArtifacts are written to `dist/release/`:\n\n- `brr-0.4.1-linux-\u003carch\u003e`\n- `brr_0.4.1-1_\u003cdeb-arch\u003e.deb`\n- `brr-0.4.1-1.\u003crpm-arch\u003e.rpm`\n- `SHA256SUMS`\n\n## Notes\n\n- Default bpffs path: `/sys/fs/bpf`\n- Optional `bpftool`: enriches mixed inspect output when available\n- `perf` command-line tool: not used by `brr`\n- Runtime stats are enabled temporarily with `BPF_ENABLE_STATS`; `brr` does not\n  write to `/proc/sys/kernel/bpf_stats_enabled`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftanelpoder%2Fbrr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftanelpoder%2Fbrr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftanelpoder%2Fbrr/lists"}