perf_event_open実験

perfが実際にどのシステムコールを使って計測しているのかを、straceperf stat自体をトレースして観察した記録。

strace -f -e trace=perf_event_open /usr/lib/linux-tools/6.8.0-100-generic/perf stat ls

#linux #performance #profiling

観察結果

lsを1回実行しただけでperf_event_open(2)が何度も呼ばれていた。task-clock, context-switches, page-faults, cycles, instructions, branches, branch-missesなど、計測したいイベント1つにつき1回呼ばれており、man 2 perf_event_openの「計測対象1つにつき1つのfdを作る」という説明と一致する。

perf_event_open({type=0xa, size=0x88, config=0xc2, ..., disabled=1, inherit=1,
  exclude_kernel=1, exclude_hv=1, enable_on_exec=1, exclude_guest=1, ...},
  1702198, -1, -1, PERF_FLAG_FD_CLOEXEC) = 21

EACCES→リトライのペアが頻出する

多くのイベントで、同じattrをほぼそのまま2回呼んでいるペアが見られた。

perf_event_open({..., (exclude_kernelなし) ...}) = -1 EACCES (Permission denied)
perf_event_open({..., exclude_kernel=1, ...}) = 22

1回目はカーネル空間も含めて計測しようとして権限不足で失敗し、2回目にexclude_kernel=1(ユーザー空間のみ計測)へフォールバックして成功している。原因はこのマシンの/proc/sys/kernel/perf_event_paranoid2になっていること。

$ cat /proc/sys/kernel/perf_event_paranoid
2

perf_event_paranoidの値による制限(man 2 perf_event_openの該当箇所より):

意味
-1 制限なし
0 rawトレースポイント含め計測可能、CAP_PERFMON/CAP_SYS_ADMINなしでも可
1 CPUイベントはユーザー空間・カーネル空間とも計測可能
2 ユーザー空間の計測のみ許可(デフォルト、Ubuntuの既定値)
3+ (Ubuntu独自拡張)CAP_SYS_PTRACEもなければユーザー空間すら計測不可

sudoersにperfをNOPASSWDで登録していても、この制限自体は別軸(カーネルのsysctl)で効くため、非rootでperf statを叩くとカーネル空間側のイベントは素通しでは取れず、exclude_kernel=1への自動フォールバックという形で観測できた。

type=0xaの謎はPMUの動的タイプ番号

straceの出力でtype=0xa /* PERF_TYPE_??? */のように?表示になっている箇所があった。straceが知っている固定のPERF_TYPE_HARDWAREなどのenumには載っていない値のため。実体はカーネルが動的に採番するPMUタイプ番号で、/sys/bus/event_source/devices/<pmu名>/typeで確認できる。

$ cat /sys/bus/event_source/devices/cpu_atom/type
10
$ cat /sys/bus/event_source/devices/cpu_core/type
4

0xa = 100x4 = 4と一致しており、type=0xaは「Atomコア(高効率コア)のPMUで計測せよ」という指定だったことが分かる。

ハイブリッドCPUで両コア種別が個別に計測される

このマシンのCPUは13th Gen Intel Core i7-1355U(P-core/E-coreのハイブリッド構成)。perf statの出力にもcpu_atom/cycles/ucpu_core/cycles/uが両方現れ、後者は<not counted>だった。

           664,414      cpu_atom/cycles/u
     <not counted>      cpu_core/cycles/u                     (0.00%)

perfはハイブリッドCPUに対してcpu_atomcpu_coreそれぞれ別のPMUとしてperf_event_open()を呼んでおり、lsのような短命なプロセスがたまたまE-core(cpu_atom)側のスレッドで実行されたため、そちら側のカウンタしか値が付かなかったと考えられる。実際perf_event_openのトレース後半でも、PERF_TYPE_HARDWAREconfig=0xa<<32|PERF_COUNT_HW_CPU_CYCLES(cpu_atom)とconfig=0x4<<32|PERF_COUNT_HW_CPU_CYCLES(cpu_core)の両方が呼ばれており、configの上位32bitにPMUタイプ番号をエンコードして「どちらのコア種別のカウンタか」を指定していることが確認できた。

perfの中での位置づけ

perfコマンド自体が何をしているかという実装原理の裏取り実験。straceperf自身をトレースするという、実験対象と観察ツールが入れ子になった構成になっている。

出典

  • man 2 perf_event_open
  • 上記のstrace出力・/proc/sys/kernel/perf_event_paranoid/sys/bus/event_source/devices/*/typeは本マシン上で実際に取得した一次情報
作成日時: 2026-08-16 08:00 / 更新日時: 2026-08-16 08:00