mcpField
C
codeprobe-performance

codeprobe-performance

github.com/machineroom-devその他5109 回インストール6 日前に更新
リポジトリ

codeprobe-performance について

コードベースの性能とスケーラビリティを監査するコードレビュー用スキルです。クエリ、メモリ使用、キャッシュ、並行処理、アルゴリズム効率、フロントエンド性能を確認します。

主な機能

  1. 01N+1と無制限クエリの検出
  2. 02インデックスとキャッシュ動作の確認
  3. 03メモリとアルゴリズム効率の問題を指摘
  4. 04並行処理のリスクを確認
  5. 05フロントエンド性能の問題を検出

活用シーン

  1. 01リクエスト処理のクエリ負荷の監査
  2. 02大規模データ処理のレビュー
  3. 03キャッシュ無効化とジョブの冪等性の確認
  4. 04高コストな描画やインポートの特定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/machineroom-dev/codeprobe --skill codeprobe-performance

インストール後、Claude Code で/codeprobe-performanceを入力して読み込まれたか確認します。

詳細

スタンドアロンモード

オーケストレーター経由ではなく直接呼び出された場合は、最初に次の操作を行ってください。

  1. 出力規約、実行モード、制約を確認するため、../codeprobe/shared-preamble.md を読み込みます(ユーザーのプロジェクトではなく、この SKILL.md の場所を基準に、兄弟ディレクトリである codeprobe スキルディレクトリからの相対パスとして解決します)。
  2. プロジェクトの技術スタックに応じて、該当する参照ファイルを ../codeprobe/references/ から読み込みます(同じ方法で解決します)。
  3. ユーザーから別の指定がない限り、デフォルトで full モードを使用します。

パフォーマンスとスケーラビリティの監査

対象範囲

このサブスキルでは、次のカテゴリにわたるパフォーマンスとスケーラビリティの問題を検出します。

  1. N+1 クエリ — ループ内でのリレーションシップの遅延読み込み
  2. インデックスの不足 — インデックスのない列を対象とした WHERE/ORDER BY
  3. 上限のないクエリ — ページネーションや上限を指定しない Model::all()
  4. メモリ — ファイル全体をメモリに読み込む処理、ループ内での配列への蓄積
  5. キャッシュ — 同一クエリの繰り返し実行、TTL の不足、書き込み後のキャッシュの陳腐化
  6. アルゴリズム効率 — ホットパスでの O(n^2)、入れ子のループ、ループ内でのソート
  7. 並行性 — 競合状態、冪等でないキュージョブ、共有された可変状態
  8. フロントエンドのパフォーマンス — 不要な再レンダリング、バンドルサイズ、遅延読み込みの不足

検出対象外

  • ホットパス以外のコードに対する時期尚早な最適化 — 適切な設計は処理の規模に応じて異なります。起動時に一度だけ呼び出されるユーティリティ関数に、リクエストハンドラーと同じ最適化は必要ありません。
  • 開発時のみのデバッグクエリ — シーダー、開発時のみのコマンド、デバッグエンドポイント内のクエリ。
  • バッチ処理スクリプト — マイグレーションやデータの一括更新など、すべてのデータを処理することを意図したスクリプトでは、上限のないクエリが適切な場合があります。
  • 小規模で上限のあるコレクション(100 件未満)に対する O(n^2) — 要素数が少なく既知の配列に対する入れ子のループは問題ありません。
  • フロントエンドの SSR/ビルド時コード — サーバーコンポーネントやビルドスクリプトのパフォーマンス特性は、クライアント側のコードとは異なります。

検出手順

N+1 クエリ
ID プレフィックス検出対象検出方法重大度
PERFイーガーロードなしでループ内から Eloquent のリレーションシップにアクセスする処理コレクションを反復処理する foreach/for ループを検索し、ループ本体内でリレーションシップのプロパティ(例:$order->items、$user->profile)にアクセスしているか確認します。コレクションを取得したクエリで、そのリレーションシップに対して with() または load() が指定されているか確認します。Major
PERF反復処理内での ORM の遅延読み込み全般ループ内で暗黙的にデータベースクエリが実行されるパターンを探します。たとえば、反復ごとにアクセスされる Django の QuerySet、SQLAlchemy の遅延読み込み、.map() 内での Prisma のリレーションシップへのアクセスなどです。Major
PERFクエリを発生させるテンプレート/ビューBlade テンプレート、Jinja2 テンプレート、React コンポーネント内で、レンダリング中にクエリを発生させるリレーションシップのプロパティを呼び出していないか確認します。Major
インデックスの不足
ID プレフィックス検出対象検出方法重大度
PERFインデックスのない列を対象とした WHERE/ORDER BYクエリ条件(where()、orderBy()、WHERE、ORDER BY)をマイグレーションファイルまたはスキーマ定義と照合し、対応するインデックスがあるか確認します。Major
PERFインデックスのない外部キーマイグレーションファイル内で、対応するインデックス定義がない foreignId()、foreign()、references() を確認します。多くの ORM ではこれらが自動的に追加されますが、直接記述したマイグレーションでは不足している場合があります。Minor
PERF複合インデックスが必要な複合クエリ同じクエリ内で異なる列に対して複数の where() 条件を使用する場合や、複合インデックスが有効な where() と orderBy() の組み合わせを確認します。Minor
上限のないクエリ
ID Prefix検出対象検出方法重大度
PERF上限のない Model::all() または SELECT *.all()、::all()、findAll()、LIMIT のない SELECT * FROM、paginate()、take()、または limit() を検索します。Major
PERF大規模なデータセットの処理でカーソル/チャンクを使用していない大規模なデータセットの処理時に、get() でコレクション全体を取得する、または読み込む操作です。cursor()、chunk()、lazy()、または同等のストリーミング方式を使用する必要があります。Major
メモリ
ID Prefix検出対象検出方法重大度
PERFファイル全体をメモリに読み込むユーザーのアップロードファイルや大きなファイルに対する file_get_contents()、可変サイズのファイルに対する fs.readFileSync()、サイズ制限のない Python の open().read()。Major
PERFループ内での配列への蓄積上限やクリア処理なしにループ内で増加する配列。ストリーミングまたは yield で処理できる結果をメモリに収集しています。Minor
PERFジェネレーターではなく大きなコレクションを使用大規模なデータセットでメモリ効率を高めるには、ジェネレーター(yield)、遅延コレクション、またはイテレーターが適しているにもかかわらず、配列/リスト全体を返しています。Minor
キャッシュ
ID Prefix検出対象検出方法重大度
PERF同一リクエスト内で同じクエリを繰り返し実行結果をキャッシュせず、同じクエリパターンを単一のリクエスト/関数呼び出し内で複数回実行しています。Minor
PERFTTL のないキャッシュ有効期限を指定しない Cache::put()、cache.set()、Redis の SET。データを無期限にキャッシュすると、古くなるおそれがあります。Minor
PERF書き込み後にキャッシュを無効化していない関連するキャッシュエントリーをクリアまたは更新しない書き込み操作(作成/更新/削除)。変更後も古いキャッシュが提供されます。Major
アルゴリズムの効率
ID Prefix検出対象検出方法重大度
PERFホットパスにおける O(n^2) 以上の計算量同じコレクションまたは関連するコレクションを反復処理するネストされたループ。ループ内の array_search/in_array/includes()(ループ内の線形検索は O(n^2))。Major
PERFループ内でのソートループ本体内で呼び出される sort()、usort()、array_sort()、.sort()。Major
PERFハッシュマップで置き換え可能な線形検索同じ配列に対して繰り返し使用される in_array()、.includes()、.indexOf()、list.index()。先に Set/dict/ハッシュマップを構築すれば、検索ごとの計算量を O(1) にできます。Minor
並行処理
ID Prefix検出対象検出方法重大度
PERF読み取り・変更・書き込みにおける競合状態ロックせずに値を読み取り、変更し、書き戻すパターン。並行コンテキストでのカウンターのインクリメント、残高の更新、フラグの切り替えなどです。Critical
PERF冪等性のないキュージョブ重複実行を確認しないキュー/ジョブハンドラー。すでに作成済みかどうかを確認せずにリソースを作成するジョブ。ジョブが作成するデータに一意制約がありません。Major
PERF非同期コンテキストでの共有可変状態非同期ハンドラーからアクセスされるグローバル/モジュールレベルの可変変数、モジュールスコープに保存されるリクエストスコープのデータ。Major
フロントエンドのパフォーマンス
ID Prefix検出対象検出方法重大度
PERF不要な再レンダリングコストの高い計算や、レンダリングごとに新しいオブジェクト/配列の参照を受け取るコンポーネントに対して、React.memo、useMemo、useCallback がありません。JSX の props 内でオブジェクト/配列をインラインで作成しています。軽微
PERFバンドルサイズの大きなインポートimport _ from 'lodash'(ライブラリ全体をインポート)、import moment from 'moment'(date-fns や dayjs で代用できる大規模なライブラリ)、import * as icons from 'icon-library'。軽微
PERF遅延読み込みの欠如ルートレベルのコード分割に React.lazy()/動的な import() を使用していません。初回ページ読み込み時に、負荷の大きいコンポーネントをすべて即時読み込みしています。軽微
任意のスクリプト連携

/codeprobe audit の実行中にオーケストレーターが実行する scripts/complexity_scorer.py の出力が利用できる場合は、パフォーマンスのホットスポット候補となる複雑度の高い関数を特定するために使用してください。「high」または「very_high」と評価され、ホットパス(リクエストハンドラー、ループ本体、頻繁に呼び出されるユーティリティ)にも現れる関数は、アルゴリズム効率に関する指摘の有力な手掛かりです。


ID プレフィックスと修正プロンプトの例

すべての指摘には PERF- プレフィックスを付け、PERF-001、PERF-002 のように連番を振ります。

修正プロンプトの例
  • 「OrderController@index(22 行目)で、Order::query() の呼び出しに ->with('items', 'customer') を追加し、N+1 問題を修正してください。現在、orders/index.blade.php:15 の Blade ループ内で 2 つのリレーションを遅延読み込みしています。」
  • 「CatalogService.php の 30 行目にある Product::all() を Product::query()->paginate(25) に置き換えてください。全レコードを処理する場合は Product::cursor() を使用してください。現在のクエリは、すべての商品をメモリに読み込んでいます。」
  • 「ReportGenerator@aggregate(45~60 行目)では、$customers 内で $orders を反復する入れ子のループにより、計算量が O(n*m) になっています。外側のループの前に検索用ハッシュマップを作成してください:$ordersByCustomerId = collect($orders)->groupBy('customer_id')。」
  • 「src/utils/helpers.ts の 3 行目にある import _ from 'lodash' を、バンドルサイズを削減するため、import debounce from 'lodash/debounce' のような個別のインポートに置き換えてください。」

コメント