kenju's blog

About Performance Engineering and BPF

Production では BCC より libbpf + BPF CO-RE を使う方が良い

"Why We Switched from BCC to libbpf for Linux BPF Performance Analysis 2020" に書いてあるとおりなのだが、BCC (BPF Compiler Collection) ではなく、libbpf + BPF CO-RE の組み合わせを使うほうが好まれる。

なぜかというと、BCCアーキテクチャ上、BPF Program を実行するために Clang/LLVM および trace に必要な Linux kernel headers file を埋め込む必要があるのだが、それがプログラム起動時に必要な CPU/Memory リソースを押し上げる要因、及び BPF Program 開発時のビルドプロセスや Debugging の複雑化に繋がっているからだ。

NOTE: 大抵の場合、Clang, LLVM および Linux kernel headers file は合わせて 100 Mbytes を超える ことになる。

例えば、bccインストール手順 (Ubuntu) を見てもらいたい。必要な依存ソフトウェアは以下の通りである(更にここに Linux kernel headers file が加わる):

  • LLVM 3.7.1 or newer, compiled with BPF support (default=on)
  • Clang, built from the same tree as LLVM
  • cmake (>=3.1), gcc (>=4.7), flex, bison
  • LuaJIT, if you want Lua support

BTF/BPF CO-RE の開発に携わっている Facebook の @anakryiko より投稿された "BPF Portability and CO-RE" というブログにも、同様の指摘がなされている。

So far, people have been dealing with this problem by relying on BCC (BPF Compiler Collection). With BCC, you embed your BPF program C source code into your user-space program (control application) as a plain string. When control application is eventually deployed and executed on target host, BCC invokes its embedded Clang/LLVM, pulls in local kernel headers (which you have to make sure are installed on the system from correct kernel-devel package), and performs compilation on the fly.

BPF Program を実行する場合、tracepoint や kprobe/uprobe を利用して Linux kernel を trace する都合上、どうしても headers file が仕組み上必要となってくる。BCC を利用する場合は、BPF Program を実行する先のマシンでも動くように headers file を埋め込んで上げる必要もあるため、BPF Program 自体を実行処理するためのオーバーヘッドも大きくなる。

実は、それを避けるために開発が進められてきたのが BTF なのだ。というのも、BPF CO-RE においてもコンパイルのために Clang/LLVM は依然として必要 なのだが、BTF を利用し、 offsets といった struct の型情報を定められたフォーマットで記述することによって、Linux kernel headers file が不要となる。

This is an issue of relocation, and both BTF and CO-RE solve this for BPF binaries. BTF provides type information so that struct offsets and other details can be queried as needed, and CO-RE records which parts of a BPF program need to be rewritten, and how.

では、どういうときに BCC を利用する価値があるかというと、開発環境や手元の環境でとりあえず BPF っぽい何かを試してみたい時くらいであろう。というのも今までの BCC の価値の一つが、Python を interface として BPF Program を記述できることで、参入障壁を下げる(?)役割もになっていたが、 実のところ、基本的には BCC Python は deprecated 扱い になっている(USDT Support のためしばらく BCC Python tools は存在価値があるようだが、時間の問題だろう)

BPF のエコシステムが発展してきた当初は、BPF CO-RE および BTF がまだ発展途上だったため、BCC または bpftrace を使おうとしたケースも多かったと想定される。が、今は BTF および BPF CO-RE の開発が進んできたため、Best Practices がとってかわろうとしている、ということなのだ。

BPF Performance Tools (Addison-Wesley Professional Computing Series) が発売された頃には、BTF も BPF CO-RE も、1 ページに満たない分量で軽く紹介されていた程度だった。それが今や主流となるのだから、BPF 界隈の進化の速度にも驚かされる。