top コマンドはプロセス単位で CPU 使用率を見せてくれるが、「そのプロセスの内部でどの関数が CPU 時間を消費しているか」までは教えてくれない。mpstat や sar で詳細な統計を取っても、負荷の「出どころ」を関数レベルで掴む手段にはならない。
そこで使うのが perf(Linux Performance Events)だ。Linux カーネルに組み込まれたパフォーマンス計測フレームワークで、CPU のハードウェアカウンター(PMU)を使ったサンプリングにより「どの関数が何%の CPU 時間を占めているか」を可視化できる。この記事では
perf stat・perf record・perf report・perf top の実践的な使い方を、実機出力とトラブルシューティングを交えながら解説する。動作確認環境: RHEL 9.4 / Ubuntu 24.04 LTS(kernel 6.8 系)
この記事のポイント
・perf record でサンプリングし perf report で関数レベルのホットスポットを特定できる
・perf stat でキャッシュミス・分岐予測ミスなど CPU イベントを数値で計測できる
・Permission denied は /proc/sys/kernel/perf_event_paranoid を 1 に緩めると解消する
・カーネルシンボルが [unknown] になる場合は debuginfo パッケージの導入が必要
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜ perf が必要か(top では見えない問題)
top・vmstat・mpstat・sar といったツールは「CPU 全体やプロセス全体の使用率を把握する」ために優れているが、次の問いには答えられない。・Web サーバーのどのリクエスト処理パスが重いか
・カーネル内のどのシステムコールに CPU 時間が消えているか
・L3 キャッシュミスや分岐予測ミスが性能劣化の原因か
perf は CPU の PMU(Performance Monitoring Unit)ハードウェアカウンターに直接アクセスし、一定頻度でスタックトレースをサンプリングすることでこれらの問いに答える。サンプリング方式なのでオーバーヘッドは低く、本番サーバーで短時間実行しても影響は許容範囲に収まる(
-F 99 でサンプリング頻度を 1 秒 99 回に絞るのが本番の定番)。perf のインストールと動作確認
perf は Linux カーネルのソースツリーに同梱されているが、実行バイナリはディストリビューション別のパッケージとして提供される。1. インストール
RHEL 9 / AlmaLinux / Rocky Linux の場合:# perf 本体 dnf install -y perf # カーネルデバッグシンボル(シンボル名を表示するため推奨) dnf debuginfo-install -y kernel-$(uname -r)
# 実行中カーネルに対応する perf バイナリ apt install -y linux-tools-$(uname -r) linux-tools-generic
linux-tools-generic だけを入れると、実行カーネルとバージョンが食い違い「WARNING: perf not found for kernel X.X.X」と表示されることがある。uname -r で確認したカーネルバージョンと一致するパッケージを必ず導入すること。2. バージョン確認
perf --version
perf version 6.8.12
perf stat で CPU イベントの統計を取得する
perf stat は、コマンドの実行中に CPU サイクル数・命令数・キャッシュミス数・分岐予測ミス数などのハードウェアイベントを計測する。「処理が遅い原因が CPU 演算なのかメモリアクセスなのか」を数値で判断する第一歩になる。1. コマンドに直接渡して計測する
perf stat find /var -name "*.log" 2>/dev/null
Performance counter stats for 'find /var -name *.log': 214.83 msec task-clock # 0.924 CPUs utilized 187 context-switches # 870.460 /sec 3 cpu-migrations # 13.960 /sec 2,418 page-faults # 11.255 K/sec 586,412,302 cycles # 2.729 GHz 964,173,881 instructions # 1.64 insn per cycle 197,482,034 branches # 919.185 M/sec 2,741,304 branch-misses # 1.39% of all branches 73,941,208 cache-references # 344.183 M/sec 4,182,903 cache-misses # 5.66% of all cache refs 0.232474 seconds time elapsed
・insn per cycle(IPC): 1 クロックあたりの命令数。CPU が効率的に動いているかの指標。1.0 以下なら待ち時間(メモリアクセス待ちや分岐ミス待ち)が多い
・cache-misses / cache-references: キャッシュミス率。5% を超えてくると、メモリアクセスがボトルネックになっている可能性が高い
・branch-misses: 分岐予測ミス率。5% を超えると、条件分岐の多いコードパスが性能を引き下げている可能性がある
2. 実行中プロセスにアタッチして計測する
すでに起動済みのプロセスに対しては-p オプションで PID を指定する。sleep を組み合わせると計測時間を秒単位で指定できる。# httpd の PID を取得して 10 秒計測する perf stat -p $(pgrep -n httpd) sleep 10
3. システム全体を計測する
-a オプションで全 CPU コア・全プロセスをまとめて計測できる。# 30 秒間、システム全体の CPU イベントを計測する perf stat -a sleep 30
perf record と perf report でホットスポットを特定する
perf stat でイベント数を把握したら、次は「どの関数が CPU を消費しているか」を特定する。perf record でサンプリングデータを収集し、perf report で可視化するのが perf の核心的な使い方だ。1. perf record でサンプリングデータを収集する
特定のコマンドをプロファイリングする場合:perf record -g -F 99 ./myapp
perf record -g -F 99 -p $(pgrep -n httpd) sleep 30
・-g(--call-graph): コールグラフ(スタックトレース)を記録する。これがないと「どこから呼ばれているか」が見えない
・-F 99: サンプリング頻度を 1 秒あたり 99 回に設定する。デフォルトの 1000Hz は本番では避け、99Hz に絞るのが安全な運用の定番
・-p PID: 特定プロセスにアタッチする
実行が終わる(または Ctrl+C で中断する)と、カレントディレクトリに
perf.data が生成される。[ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.487 MB perf.data (1243 samples) ]
2. perf report で関数別 CPU 使用率を確認する
perf report --stdio
--stdio を付けるとテキスト出力になり、less や grep で読み込みやすくなる。付けない場合は対話的な TUI 画面が開く。実機出力例(httpd 負荷テスト中のサンプリング結果):
# Samples: 1K of event 'cycles:P' # Event count (approx.): 2716438820 # # Overhead Command Shared Object Symbol # ........ ....... .................. ............................... # 47.83% httpd httpd [.] ap_run_handler 12.41% httpd libapr-1.so.0 [.] apr_pollset_poll 9.17% httpd [kernel] [k] __softirqentry_text_start 6.08% httpd httpd [.] ap_process_request 5.21% httpd libc.so.6 [.] __strcmp_avx2 4.34% httpd httpd [.] ssl_callback_ServerHello 2.93% httpd [kernel] [k] sock_recvmsg 1.89% httpd [kernel] [k] tcp_recvmsg 1.24% httpd httpd [.] ap_read_request
・Overhead: この関数(シンボル)が全サンプルに占める割合。上位に来るほど CPU を多く使っているボトルネック候補
・Shared Object の [kernel]: カーネル空間での処理。I/O やネットワークのシステムコストがここに出る
・Symbol が [unknown]: デバッグシンボルが不足している。後述のトラブルシュートを参照
コールグラフ(呼び出し元チェーン)を展開して確認するには
--call-graph=dwarf を追加する:perf report --stdio --call-graph=dwarf | head -100
perf top でリアルタイムにホットスポットを確認する
perf top は top コマンドの関数版で、「今この瞬間どの関数が CPU を使っているか」をリアルタイムで表示する。perf.data への保存が不要なため、perf record より手軽に使える。perf top -F 99 -g
perf top -F 99 --stdio
・Enter キー: 選択した関数のコールグラフを展開する
・A キー: アノテーション表示(アセンブリコードとシンボルの対応)
・E キー: ソースコード表示(debuginfo がある場合のみ)
・q キー: 終了
本番サーバーで「今すぐ重い関数を確認したい」場面では
perf top が最速の手段だ。「Permission denied」エラーとシンボル未表示のトラブルシュート
「You may not have permission to collect system-wide stats」が出る場合
root 以外のユーザーが perf を実行すると権限エラーになることがある。原因は/proc/sys/kernel/perf_event_paranoid の設定値だ。cat /proc/sys/kernel/perf_event_paranoid
3
・-1: すべての計測を一般ユーザーに許可(セキュリティリスクあり)
・0: 一般ユーザーが CPU ハードウェアカウンターを使える
・1: カーネル空間プロファイリングを除き一般ユーザーも使える(本番で緩める場合の推奨値)
・2(Ubuntu のデフォルト): root と CAP_PERFMON 権限を持つユーザーのみ
・3(RHEL 9 のデフォルト): root と CAP_PERFMON のみ。システム全体の計測は禁止
一時的に緩める(再起動で元に戻る):
echo 1 | sudo tee /proc/sys/kernel/perf_event_paranoid
/etc/sysctl.d/99-perf.conf を作成して sysctl --system を実行する:kernel.perf_event_paranoid = 1
カーネルシンボルが [unknown] になる場合
perf report の Symbol 列が大部分 [unknown] になる場合、カーネルデバッグシンボルが入っていない。RHEL 9 / AlmaLinux / Rocky Linux:
dnf debuginfo-install kernel-$(uname -r)
# Ubuntu Debugsymbols リポジトリを有効化 echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse" \ | sudo tee /etc/apt/sources.list.d/ddebs.list sudo apt install ubuntu-dbgsym-keyring sudo apt update sudo apt install linux-image-$(uname -r)-dbgsym
-g(デバッグ情報)と -fno-omit-frame-pointer(フレームポインタ保持)を付けてリビルドする。これがないと関数名やコールグラフが正確に取れない。「WARNING: Kernel address maps are restricted」が出る場合
/proc/sys/kernel/kptr_restrict の値が高いと、カーネルシンボルへのアクセスが制限される。# 現在の値を確認する cat /proc/sys/kernel/kptr_restrict # 一時的に解除する(再起動で元に戻る) echo 0 | sudo tee /proc/sys/kernel/kptr_restrict
perf でボトルネックを特定できたら、次はサーバー全体のパフォーマンスチューニングスキルを体系的に固めませんか?
perf のような「見えない障害を可視化する技術」を現場で使いこなせるのは、Linuxの内部構造を体系的に理解しているエンジニアだけです。
ネットの断片情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。
「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。
本記事のまとめ
| やりたいこと | コマンド |
|---|---|
| コマンドの CPU イベントを計測する | perf stat ./myapp |
| 実行中プロセスを 10 秒計測する | perf stat -p PID sleep 10 |
| システム全体を 30 秒計測する | perf stat -a sleep 30 |
| コマンドをサンプリングして perf.data を生成 | perf record -g -F 99 ./myapp |
| 実行中プロセスを 30 秒サンプリング | perf record -g -F 99 -p PID sleep 30 |
| 関数別 CPU 使用率をテキストで確認 | perf report --stdio |
| コールグラフ付きで確認する | perf report --stdio --call-graph=dwarf |
| リアルタイムにホットスポットを確認 | perf top -F 99 -g |
| 権限エラーを一時的に解除する | echo 1 | sudo tee /proc/sys/kernel/perf_event_paranoid |
| カーネルシンボルアクセス制限を一時解除 | echo 0 | sudo tee /proc/sys/kernel/kptr_restrict |
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:bashのcallerコマンドでシェルスクリプトのコールスタックを記録する方法|エラー発生箇所と呼び出し元ログの設計
- この記事の属するカテゴリ:Linuxtips・Linuxトラブルシューティングへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます