performance-review について
コードの時間・空間計算量のホットスポットを静的解析するスキルです。Python は常に解析し、オプション依存関係があれば対応言語やコールグラフの解析も追加します。
主な機能
- 01標準ライブラリ AST で Python を解析
- 02時間・空間計算量のホットスポットを検出
- 03オプションで JS/TS などを解析
- 04コールグラフ情報で重要度を引き上げ
- 05分類済みの Markdown レポートを生成
活用シーン
- 01マージ前の変更コードレビュー
- 02遅さが疑われる関数の調査
- 03リファクタリングによる二次計算量の確認
- 04AI 生成コードのネストしたループを点検
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ athola/ claude-night-market --skill performance-reviewインストール後、Claude Code で/performance-reviewを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
modules/gauntlet-integration.mdkuva-visualization.mdmemory-allocation-lenses.mdspace-complexity.mdtime-complexity.md詳細
パフォーマンスレビュー
時間計算量と空間計算量のホットスポットを静的解析でレビューします。
このスキルは、段階的に強化される3つのティアで実行されます。ティア1ではPythonの標準ライブラリastを使用し、常に実行されます。ティア2では、tiersエクストラがインストールされている場合にtree-sitterを使用し、JS/TS、Go、Rust、Java、C/C++の検出に対応します。ティア3では、各指摘からgauntletの呼び出しグラフを順方向にたどり、呼び出し先にホットスポットがあれば重大度を1段階引き上げます。gauntletプラグインをインポートでき、.gauntlet/graph.dbが存在する場合に実行されます。これらがない場合、ティア2とティア3は何もせず、ティア1は引き続きPythonソースの指摘を生成します。
クイックスタート
/performance-review # scan changed files
/performance-review path/to/file.py # scan one file
/performance-review --tier 1 # force Tier 1 only
プログラムからの使用:
from pensive.skills.performance_review import PerformanceReviewSkill
skill = PerformanceReviewSkill()
result = skill.analyze(context, "src/module.py")
for f in result.issues:
print(f"[{f.severity}] {f.file}:{f.line} {f.message}")
使用する場面
- ユーザー入力の規模に応じて実行時間が増えるコードの、マージ前レビュー。
- プロファイラーを使う前に、「遅い気がする」関数を調査するとき。
- リファクタリングで新たに導入されたO(n²)パターンの監査。
- ネストしたループのホットスポットが多い、AI生成コードのガードレール。
使用しない場面
- 実行時の測定(メモリプロファイル、実データでのCPU時間)が必要な場合。代わりに
Skill(parseltongue:python-performance)を使用してください。このスキルはcProfile、py-spy、ベンチマークを実行します。 - ホットスポットに特化しない一般的なリファクタリングの指針が必要な場合は、より広範な最適化パターンを扱う
algorithm-efficiencyモジュールを含むSkill(pensive:code-refinement)を使用してください。このスキルは検出し、あちらのスキルは手法を説明します。 - 手作業で行うループ変換(アンローリング、手動SIMD、ストレングスリダクション)を維持する価値があるか判断する場合は、手動最適化とコンパイラーの判断基準を扱う
Skill(leyline:loop-optimization)を使用してください。このスキルはホットスポットの形を指摘しますが、変換方法は判断しません。 - アーキテクチャレベルのパフォーマンス(シャーディング、キャッシュレイヤー、キューの配置)については、
Skill(pensive:architecture-review)を使用してください。
必須の進捗項目
perf-review:context-establishedperf-review:scan-completeperf-review:findings-categorizedperf-review:integration-checkedperf-review:report-generatedperf-review:findings-verified
ワークフロー
ステップ1:コンテキスト(perf-review:context-established)
- 対象ファイルを特定します。引数なしで実行した場合は、
git diff --name-onlyを使用します。パスを指定した場合は、その範囲に限定します。 - 対象の言語を確認します。ティア1はPythonに対応します。Python以外のファイルをティア2で解析するには、
tiersエクストラが必要です。
ステップ2:ティア1 ASTスキャン(perf-review:scan-complete)
時間計算量のパターンについてはmodules/time-complexity.mdを、空間計算量のパターンについてはmodules/space-complexity.mdを読み込みます。各モジュールには、すべての検出器が対象とするASTの形状が記載されています。
自動スキャンに加えて、modules/memory-allocation-lenses.mdを読み込み、3つの手動の観点(外部ソース由来の上限のないコレクション、ホットパスでの再計算、直列的なブロッキングI/O)を適用し、対象ファイルを読んで確認します。
Pythonの対象ファイルごとに、次を呼び出します。
from pensive.skills.performance_review import PerformanceReviewSkill
result = PerformanceReviewSkill().analyze(context, path)
ビジターはASTを1回走査し、ReviewFindingレコードを出力します。
ステップ3:分類と優先順位付け(perf-review:findings-categorized)
指摘を重大度別に分類します。
- HIGH:入力サイズに応じて増加するイテラブルに対するO(n²)以上の処理(T1、T2)。
- MEDIUM:上限のない割り当て、または反復ごとのオーバーヘッド(T3、T4、S1、S3)。
- LOW:スタイルレベルの非効率性(T5、T6、S2)。
- CRITICAL:ティア3での推移的な重大度引き上げ用に予約されています。
同じ重大度内では、ファイル、次に行番号の順で並べ替えます。対象の読み込み時点でユーザーが許容すると明示した指摘(TODO/コメントのマーカー)は抑制します。
ステップ 4:Tier 2/3 による拡充(perf-review:integration-checked)
契約については modules/gauntlet-integration.md を読み込みます。
tree_sitter_language_pack をインポートできる場合は、ステップ 2 でスキップした Python 以外のファイルに Tier 2 を実行します。gauntlet をインポートでき、スキャン対象ファイルのディレクトリまたはいずれかの親ディレクトリに .gauntlet/graph.db が存在する場合は、推移的な呼び出し先のホットスポットに基づいて重要度を引き上げるため、Tier 3 を実行します。
追加機能がない場合、このステップは何も行わず、レポートには「Tier 2/3 not available: install pensive with the tiers extra for multi-language and call-chain coverage.」と記載されます。tree-sitter で解析できないファイルがあると警告が追加され、Tier 2 の検出結果はありません。
ステップ 5:レポート(perf-review:report-generated)
Markdown レポートを出力します。
## Performance Review: <target>
### HIGH (<count>)
- src/foo.py:42: Nested loop over the same iterable 'items'.
Suggestion: sort + two pointers, or hash-set membership.
### MEDIUM (<count>)
- ...
### LOW (<count>)
- ...
Tier coverage: 1 (always) | 2 (gauntlet ✓/✗) | 3 (graph ✓/✗)
レポートは参考情報です。修正は Skill(pensive:code-refinement) を使用するか、手動でマージしてください。
段階的な分析
| Tier | ソース | 実行条件 | 対象範囲 |
|---|---|---|---|
| 1 | 標準ライブラリ ast | 常時(Python ソースのみ) | T1-T6、S1-S3 |
| 2 | tree_sitter_language_pack | インポート可能な場合、Python 以外のファイルに対して実行 | JS/TS、Go、Rust、Java、C/C++ の T1、T2、S1(Java と C は T1 のみ) |
| 3 | gauntlet.graph.GraphStore | インポート可能で、ファイルより上の階層に .gauntlet/graph.db が見つかった場合 | CALLS で到達可能な関数がホットスポットを持つ場合に、重要度を 1 段階引き上げ |
出力形式
検出結果には、pensive.skills.base の共通 ReviewFinding データクラスを使用します。
ReviewFinding(
file="src/module.py",
line=42,
severity="HIGH", # LOW | MEDIUM | HIGH | CRITICAL
category="time", # time | space
message="Nested loop over the same iterable 'items'.",
suggestion="Sort + two pointers, or hash-set membership.",
anchor="verbatim source text at file:line",
code_snippet="",
)
この形式は他のすべての pensive レビュースキルと一致するため、検出結果を変換せずに Skill(pensive:unified-review) へ渡せます。
プラグイン間の依存関係
| 依存関係 | 必須? | 不足時の影響 |
|---|---|---|
tree_sitter_language_pack | 任意(tiers extra) | Tier 2 は [] を返します。Python の対象範囲は変わりません |
gauntlet.graph.GraphStore | 任意(gauntlet プラグイン、PyPI では提供されていません) | Tier 3 は [] を返します。重要度は引き上げられません |
任意インポートの契約は、plugins/leyline/src/leyline/tokens.py:25-32 の前例に従います。モジュールレベルのセンチネルに対して try-import を行い、各 Tier ヘルパー内で None の場合は早期リターンします。plugins/gauntlet/hooks/precommit_gate.py:35-40 は同じ形式のブール値フラグ版です。正確なコード形式については modules/gauntlet-integration.md を参照してください。
関連モジュール
modules/time-complexity.md:T1-T6 の検出パターンと AST の形式。modules/space-complexity.md:S1-S3 の検出パターン。modules/gauntlet-integration.md:Tier 2/3 の契約、フォールバックの動作、例。modules/kuva-visualization.md:kuva を使用してベンチマークデータをチャートとして描画します(criterion、pytest-benchmark、アドホックな表)。チャートによる証拠が作業証明要件を満たす場合について説明します。modules/memory-allocation-lenses.md:手動レビューの観点(AST 検出器ではありません)。外部ソースからデータを受け取る上限のないコレクション、メモ化すべきホットパスでの再計算、上限のない集合に対する直列のブロッキング I/O を対象とします。コードを読んで適用してください。自動化されていないため、「テスト」の検出器テストのルールはこれらを対象としていません。
検証
パフォーマンスレビューの指摘は、呼び出し元が実際の問題だと確認できて初めて役に立ちます。指摘を修正する価値があると判断する前に、次のチェックリストを使用してください。
- プロファイラーを使って再現します。 ホットスポットで
cProfile、py-spy、または言語固有の同等ツールを実行します。指摘は AST の形状を特定し、プロファイラーは実行時の影響を検証します。 - 失敗したベンチマークを再実行します。
benches/が存在する場合、ホットスポットは AST スキャンだけでなく、数値にも現れるはずです。 - 提案した修正の前後で数値を比較します。 数値に変化がなければ、その修正は誤りです。修正前と修正後の計測時間をそれぞれ
[E1](修正前)、[E2](修正後)のような証拠参照として記録します。データポイントが 3 つ以上ある場合は、kuva チャートを作成して PR に添付します(modules/kuva-visualization.mdを参照)。 - 報告されたホットスポットを 2~3 件、手動でサンプリングします。 呼び出し元で短絡評価される場合、AST レベルでは正しくても、呼び出しグラフレベルでは誤りとなることがあります。手動サンプリングでこの問題を検出できます。
Skill(imbue:proof-of-work) の規律が適用されます。「ホットスポットを修正した」といった主張には、断言ではなく証拠が必要です。
テスト
AST 形状検出器を対象としたテストファイルが、すでに plugins/pensive/tests/skills/test_performance_review.py にあります。ここを変更する際のルールは 2 つです。
- 新しい検出器にはテストを追加します。 モジュールに追加する新しい T-* または S-* パターンには、それを実行する最小の AST サンプルを使ったテストを用意します。
- 削除する誤検出には回帰テストを追加します。 以前はホットに見えていた形状に対してスキルが起動しなくなった場合、その理由をテストケースに示し、後から回帰を検出できるようにします。
鉄則が適用されます。まず失敗するテストを用意せずに新しい検出器を追加するのは、コード分析コンポーネントで TDD を省略するということです。TDD が最も効果を発揮するのは、まさにこの領域です。
指摘の根拠を検証する(perf-review:findings-verified)
指摘を .review/findings.json に記録し、引用検証ツール(Skill(imbue:review-core) のステップ 5)を実行して、検証ツールが却下した項目は削除するか UNVERIFIED とラベル付けします。
完了条件
- 指定された対象のパフォーマンスレビュー報告ファイルが存在する。
- すべての指摘に重大度ラベルと、呼び出し元が実行できる具体的な提案が含まれている。
- 時間計算量(T1-T6)および空間計算量(S1-S3)の検出器が実行され、ティアの網羅状況が報告されている。
- ティア 2(tree-sitter)とティア 3(グラフストア)のコントラクトは、オプショナルインポートのセンチネルに従っている。モジュールが見つからない場合は、例外を発生させず
[]を返す。 - 新しい検出器には、それが存在する前は失敗する最小 AST テストを用意する。削除する誤検出には回帰テストを用意する。
- 統合エントリーポイントから呼び出したとき、指摘が変換されずに
Skill(pensive:unified-review)に渡される。 - 報告されたすべての指摘に、
citation_verifier.py(終了コード0)で確認されたLocationと逐語的なAnchorが含まれている。または、未検証の指摘が削除されるか、UNVERIFIEDとラベル付けされている。