performance-tuning について
performance-tuningは、ソフトウェアの性能問題を調べる開発者やコーディングエージェント向けのスキルです。測定可能な目標を定め、プロファイルを取り、一度に一つ変更して再測定する手順を示します。
主な機能
- 01定量的な性能目標の設定
- 02再現可能な基準値の測定
- 03変更前のプロファイリング
- 04一項目ずつ変更して測定
- 05性能回帰を防ぐチェック
活用シーン
- 01応答遅延やタイムアウトの調査
- 02予算に照らしたメモリやバンドルサイズの評価
- 03提案した最適化の効果測定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ noobygains/ godmode --skill performance-tuningインストール後、Claude Code で/performance-tuningを入力して読み込まれたか確認します。
詳細
パフォーマンスチューニング
時間がどこにかかっているかについての直感は、当たるよりも外れることのほうが多いものです。問題を測定し、プロファイルを使って実際に時間やメモリがどこで使われているかを特定し、変更を1つ加えて、同じ方法でもう一度測定します。測定なしに最適化はありません。変更はすべて、変更前に数値で正当性を示し、変更後に数値で効果を証明します。
最優先の原則
NO OPTIMISATION WITHOUT A MEASUREMENT PROVING THE PROBLEM
例外はありません。回避策もありません。近道もありません。
適用する場合
必須:
- ユーザー、テスト、またはモニターから、遅さ、タイムアウト、高いメモリ使用量、大きなバンドル、または高コストが報告された場合。
- パフォーマンス予算または目標(レイテンシのパーセンタイル、Core Web Vitals、バンドルサイズ、クエリ時間、コールドスタート)を超過した場合。
- 「最適化して」「高速化して」「スケールできるようにして」と依頼された場合。
- キャッシュ、インデックス、並行処理、別の言語での書き換え、またはマイクロ最適化を追加しようとしている場合。
適用しない場合:
- コードがまだ正しく動作しない場合。まず正しさを優先し、
godmode:fault-diagnosisまたはgodmode:test-firstを使用してください。 - 目標も苦情もない場合。「いつか遅くなるかもしれない」は問題ではありません。記録して先に進んでください。
- コードを書き始める際に、妥当なアルゴリズムやデータ構造を選ぶ場合。それによって明瞭さが損なわれない限り、これは通常の設計であり、チューニングではありません。
手順
digraph perf {
rankdir=TB;
target [label="1. Target\n(number + percentile)", shape=box];
baseline [label="2. Baseline\n(repeatable measurement)", shape=box];
met [label="Target met?", shape=diamond];
profile [label="3. Profile\n(where does it go?)", shape=box];
hypo [label="4. One hypothesis", shape=box];
change [label="5. Change one thing", shape=box];
remeasure [label="6. Re-measure\n(same method)", shape=box];
better [label="Significant\nimprovement?", shape=diamond];
revert [label="Revert", shape=box];
done [label="7. Record + guard", shape=box];
target -> baseline -> met;
met -> done [label="yes"];
met -> profile [label="no"];
profile -> hypo -> change -> remeasure -> better;
better -> met [label="yes, keep"];
better -> revert [label="no"];
revert -> hypo;
}
-
目標を設定します。 数値、パーセンタイル、状況を定めます。「毎秒50リクエスト時の
GET /ordersを p95 で300 ms未満にする」「モバイルで75パーセンタイルの LCP を2.5秒以下にする」「gzip 圧縮後のバンドルを200 KB未満にする」などです。目標がなければ終了条件もありません。ユーザーに確認するか、目標を提案してください。 -
再現可能なベースラインを測定します。 入力データと環境(デバッグビルドではなく、本番環境に近いもの)を統一し、ウォームアップ実行を除外して複数回実行し、単一の数値ではなくばらつきも報告します。実行した正確なコマンドと出力を保存してください。ツールは以下の表にあります。
-
推測する前にプロファイルを取ります。 プロファイラー、クエリプラン、トレース、またはバンドルアナライザーを使って、時間、メモリ、またはバイト数がどこで使われているかを特定します。証拠として、ホットスポットを示すプロファイル成果物(フレームグラフ、
EXPLAIN ANALYZEの出力、トレース)を残します。よくある原因を大まかな順に挙げると、データベースクエリ(N+1、インデックス不足、全件スキャン)、順次行われるネットワークの往復、過大なペイロードのシリアライズ、アルゴリズムの計算量、同期 I/O、メモリの頻繁な割り当てです。 -
ホットスポットと変更を結び付ける仮説を1つ立てます。 例:「注文一覧では項目ごとにクエリを1回実行しています(N+1)。1回の結合クエリにすれば、p95 を920 msから300 ms未満に短縮できるはずです。」
-
変更は1つだけ加えます。 効果の因果関係を特定できるよう、テストが通ることを確認したうえで、測定ごとに変更を1つだけ行います。変更は独立したコミットにします。
-
同一の方法で再測定し、ばらつきを含めてベースラインと比較します。 改善が測定誤差の範囲内である場合や、期待した結果に届かない場合は、「効果があるはず」でも元に戻してください。効果があれば、新しいベースラインで目標を達成するまで、手順2に戻ります。
-
記録し、再発を防ぎます。 変更前後の数値、測定方法、コミットを PR の説明に記載します。CI のベンチマーク、予算チェック(
godmode:quality-gates)、またはクエリ数を検証するテストなど、性能劣化が気付かれないまま再発しないためのガードを追加します。
計測ツール
| 対象 | 計測方法 | プロファイリング |
|---|---|---|
| コマンドまたはスクリプト全体 | hyperfine --warmup 3 'cmd'(2つを比較する場合:hyperfine 'old' 'new') | 以下の言語別プロファイラー |
| Python | pytest-benchmark、timeit | py-spy record -o profile.svg -- python app.py、py-spy top --pid <pid> |
| Node.js | hyperfine、ベンチマークライブラリ | node --cpu-prof app.js(CPU)、node --heap-prof app.js(メモリ)。ファイルをブラウザーの DevTools で開きます |
| Go | go test -bench . -benchmem | go test -bench . -cpuprofile cpu.out を実行し、その後 go tool pprof cpu.out |
| Rust | Criterion などのベンチマークハーネス | Linux で perf またはフレームグラフツール |
| PostgreSQL のクエリ | EXPLAIN (ANALYZE, BUFFERS) <query> | 同じ実行計画を確認します。シーケンシャルスキャン、行数見積もりの誤差、ループを探します |
| 高負荷時の HTTP サービス | 固定リクエストレートでパーセンタイルを報告する負荷生成ツール | APM トレース、またはサーバー上の言語別プロファイラー |
| Web ページ | lighthouse <url>(ラボデータ)、Core Web Vitals の実ユーザーデータ | ブラウザーの DevTools の Performance パネル |
| バンドルサイズ | バンドラーの分析ツール、またはサイズ上限チェック | 同じ分析ツールでモジュールごとに確認 |
EXPLAIN ANALYZE は文を実行します。INSERT、UPDATE、DELETE の場合は、トランザクション内で実行してロールバックしてください。
予算
予算を設定すると、「十分に速い」をチェック可能な基準にできます。ユーザーが結果を実感する箇所に予算を設定し、CI で適用してください。
| 種類 | 予算の例 | 数値の根拠 |
|---|---|---|
| Largest Contentful Paint | 2.5 秒以下 | Core Web Vitals の「良好」基準。モバイルとデスクトップを分けたページ読み込みの 75 パーセンタイル |
| Interaction to Next Paint | 200 ミリ秒以下 | Core Web Vitals の「良好」基準。75 パーセンタイル |
| Cumulative Layout Shift | 0.1 以下 | Core Web Vitals の「良好」基準。75 パーセンタイル |
| API レイテンシ | 想定負荷でのエンドポイントごとの p95 と p99 | 製品の要件、またはサービスレベル目標 |
| クエリ時間 | 本番環境相当のデータでのクエリごとの時間 | エンドポイントの予算から、それ以外のすべてを差し引いた値 |
| バンドルまたはバイナリのサイズ | エントリーポイントごとの gzip 圧縮後のサイズ | 対象デバイスとネットワークが許容できる値 |
| メモリ | プロセスごとのピーク常駐メモリ | 余裕を見込んだコンテナーまたはデバイスの上限 |
平均ではなくパーセンタイルを報告してください。平均値では、ユーザーが不満を訴える遅いリクエストが隠れてしまいます。
アンチパターン
| アンチパターン | うまくいかない理由 | 代わりに行うこと |
|---|---|---|
| 最初にキャッシュする | 古いデータ、無効化のバグ、メモリ使用量が増え、遅いコードが隠れてしまいます | 遅いクエリや呼び出しを修正します。計測で必要性を確認し、無効化の計画を立てた場合にのみキャッシュします |
| すべてにインデックスを付ける | 書き込みが遅くなり、ストレージを使用します | クエリ実行計画で必要とされるインデックスを追加し、新しい実行計画で確認します |
| すべてを非同期化または並列化する | CPU バウンドの処理では効果がなく、デバッグが難しくなり、新たな競合が発生します | プロファイルで待機が確認された、独立した I/O に並行処理を使います |
| プロファイラーで指摘されていないループをマイクロ最適化する | ナノ秒単位の節約のために、コードの明瞭さが損なわれます | ホットパス上のコードだけを変更します |
| 複数の変更を一度に行う | 何が改善または悪化させたのか分かりません | 計測ごとに変更は 1 つにします |
| デバッグビルドや少量のデータでベンチマークする | 数値を本番環境に当てはめられません | 本番環境に近いビルド、データ量、ハードウェアを使います |
| ばらつきを見ずに 1 回だけ実行する | ノイズを改善と誤認します | ウォームアップ後に複数回実行し、ばらつきを比較します |
| より高速な言語で書き直す | たいていは 1 つのクエリにあるホットスポットのために、数カ月分のリスクを負います | まずプロファイリングを行い、ホットスポットを修正します |
パフォーマンス最適化の落とし穴
| 合理化 | 真実 |
|---|---|
| 「ボトルネックがどこにあるか分かっています。」 | その思い込みが間違っていることが多いため、プロファイラーがあります。プロファイルを示してください。 |
| 「このままでは大規模になったときに遅くなります。」 | それなら負荷テストを使って、その規模で測定してください。それまでは推測にすぎません。 |
| 「キャッシュを使えばすべてが速くなります。」 | キャッシュが速くするのはキャッシュヒット時だけで、それ以外はすべてを複雑にします。まず何が遅いのかを測定してください。 |
| 「ベストプラクティスでは、ここにインデックスを追加することになっています。」 | ベストプラクティスは、あなたのクエリを把握していません。把握しているのはクエリプランです。 |
| 「ここを触っているついでに、これも調整しておきます。」 | 測定も計画もされていない変更は、次の測定にノイズを加えます。一度に変更するのは1つだけにしてください。 |
| 「速くなった気がします。」 | 感覚は測定ではありません。同じベンチマークを実行してください。 |
| 「改善幅は小さいけれど、害はないはずです。」 | 変更するたびに、分かりやすさとレビューの時間が損なわれます。ノイズの範囲内にある変更は元に戻します。 |
ガードレール
決してしないでください:
- 目標、ベースライン、プロファイルなしに最適化すること。
- 測定と測定の間に、複数の箇所を変更すること。
- 効果が測定ノイズの範囲内にある変更を残すこと。
- 測定されていない改善のために、正確性、セキュリティ、可読性を犠牲にすること。
- 平均値だけ、または1回の実行結果だけを根拠として報告すること。
必ずしてください:
- 測定コマンドとその出力を、変更前後で正確に保存すること。
- 本番環境に近いビルドと環境で測定すること。
- 最適化の各ステップでテストをすべて成功させること。
- 採用する改善にはすべて、リグレッションを防ぐ仕組み(ベンチマーク、予算、クエリ数テスト)を追加すること。
関連項目
godmode:fault-diagnosis:遅さの原因が実際にはバグ(ハング、リーク、リトライの集中)である場合は、ここで診断します。godmode:system-design:プロファイルがアーキテクチャ(データモデル、サービス境界、ホスティング)を示している場合は、その判断をここで行います。godmode:quality-gates:予算とベンチマークを CI ゲートにします。godmode:test-first:最適化によってコードを変更する前に、テストで動作を固定します。godmode:grounding:プロファイラーフラグとフレームワークのパフォーマンス機能を、最新のドキュメントと照らし合わせて確認します。godmode:completion-gate:作業が完了したことを示す根拠は、変更前後の数値です。