performance-gate
Verify performance implications were considered and no obvious anti-patterns exist. Issues result in WARNINGS.
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o performance-gate.zip https://jpskill.com/download/18287.zip && unzip -o performance-gate.zip && rm performance-gate.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/18287.zip -OutFile "$d\performance-gate.zip"; Expand-Archive "$d\performance-gate.zip" -DestinationPath $d -Force; ri "$d\performance-gate.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
performance-gate.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
performance-gateフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
Gate 4: パフォーマンスレビュー
「動くコードは第一段階。スケールするコードは第二段階。」
目的
このゲートは、パフォーマンスのアンチパターンが問題を引き起こす前に捕捉することを目的としています。焦点は、マイクロ最適化ではなく、明らかな問題に当てられます。
ゲートの状態
- PASS — 明らかなパフォーマンスの問題なし
- WARNING — スケール時に問題を引き起こす可能性のある問題が見つかりました
ゲートの質問
質問 1: スケーラビリティ
「アイテムが 10,000 個になったらどうなりますか? 1,000,000 個になったら?」
注目点:
- データ量の増加に対する認識
- 大規模データセットに対するページネーション
- 効率的なデータ構造
- 不要なループがないこと
質問 2: クエリ効率
「この操作はデータベースクエリを何回実行しますか?」
注目点:
- N+1 クエリがないこと
- 適切な場所でのバルクオペレーション
- クエリされるカラムに対するインデックス
- クエリコストに対する認識
質問 3: 再レンダリングの認識 (フロントエンド)
「この状態が変化したとき、どのコンポーネントが再レンダリングされますか?」
注目点:
- レンダリングのトリガーに対する認識
- 適切なメモ化
- 状態配置の最適化
- レンダリングにおける高コストな計算がないこと
パフォーマンスチェックリスト
データベース操作
- [ ] N+1 クエリがないこと (ループ内のクエリ)
- [ ] リストエンドポイントに対するページネーション
- [ ] 頻繁にクエリされるカラムに対するインデックス
- [ ] 必要なカラムのみを SELECT すること (SELECT * ではない)
フロントエンドレンダリング
- [ ] 高コストな計算には useMemo を使用すること
- [ ] イベントハンドラは必要に応じて useCallback を使用すること
- [ ] 大規模リストには仮想化を使用すること
- [ ] 重いコンポーネントは遅延ロードすること
API & ネットワーク
- [ ] レスポンスペイロードは最小限にすること
- [ ] 大量のデータはページネーションすること
- [ ] 適切な場所にキャッシュヘッダーを設定すること
- [ ] 冗長な API コールがないこと
一般
- [ ] 正当な理由のないネストされたループ (O(n²)) がないこと
- [ ] ブロッキング操作がないこと
- [ ] インターバル/タイムアウトのクリーンアップ
- [ ] 妥当なメモリ使用量
レスポンステンプレート
PASS の場合
✅ PERFORMANCE GATE: PASSED
パフォーマンスに関する考慮事項は良好です:
- データ取得は効率的です
- 明らかな N+1 パターンはありません
- 適切なページネーションが実装されています
次のゲートに進みます...
WARNING の場合
⚠️ PERFORMANCE GATE: WARNING
[X] 個のパフォーマンスに関する懸念が見つかりました:
**Issue 1: [N+1 Query / Inefficient Loop]**
Location: `file.ts:42`
Question: 「これは [N] 回のクエリを実行します。1 つにまとめることはできますか?」
**Issue 2: [Missing Pagination]**
Location: `file.ts:88`
Question: 「100,000 件のレコードがある場合はどうなりますか?」
**Issue 3: [Expensive Render]**
Location: `Component.tsx:15`
Question: 「これはレンダリングごとに再計算する必要がありますか?」
これらは今は問題ないかもしれませんが、アプリが成長するにつれて問題になるでしょう。
確認すべき一般的な問題
1. N+1 クエリ問題
❌ const users = await User.findAll();
for (const user of users) {
user.posts = await Post.findByUserId(user.id);
}
// 1 + N クエリ!
✅ const users = await User.findAll({
include: [{ model: Post }]
});
// JOIN を使用した 1 クエリ
2. すべてを取得する
❌ // 50 個のフィールドを持つ 10,000 人のユーザーを返します
GET /api/users
✅ // 必要なフィールドのみでページネーション
GET /api/users?page=1&limit=20&fields=id,name,email
3. 高コストなレンダリング計算
❌ function UserList({ users }) {
// すべてのレンダリングで実行されます
const sorted = users.sort((a, b) => a.name.localeCompare(b.name));
return <ul>{sorted.map(...)}</ul>;
}
✅ function UserList({ users }) {
const sorted = useMemo(
() => [...users].sort((a, b) => a.name.localeCompare(b.name)),
[users]
);
return <ul>{sorted.map(...)}</ul>;
}
4. インライン関数による再レンダリング
❌ function Parent() {
return <Child onClick={() => doSomething()} />;
// レンダリングごとに新しい関数 → Child が再レンダリングされます
}
✅ function Parent() {
const handleClick = useCallback(() => doSomething(), []);
return <Child onClick={handleClick} />;
}
5. クリーンアップの欠如
❌ useEffect(() => {
const interval = setInterval(fetchData, 5000);
// メモリリーク! 永遠に実行されます
}, []);
✅ useEffect(() => {
const interval = setInterval(fetchData, 5000);
return () => clearInterval(interval);
}, []);
ソクラテス式パフォーマンス質問
修正点を指摘する代わりに、次のように質問します。
- 「このエンドポイントは 100 人のユーザーに対して何回クエリを実行しますか?」
- 「さらに 10,000 個のアイテムを追加すると、何が壊れますか?」
- 「この配列はレンダリングごとに並べ替えられますか?」
- 「コンポーネントがアンマウントされるときに、このインターバルをクリアするものは何ですか?」
- 「このテーブルから 50 個のカラムすべてが必要ですか?」
Big O クイックリファレンス
| パターン | 複雑性 | 10,000 アイテム | 懸念レベル |
|---|---|---|---|
| マップルックアップ | O(1) | 1 op | 問題なし |
| シングルループ | O(n) | 10,000 ops | 通常は問題なし |
| ネストされたループ | O(n²) | 100M ops | 警告 |
| トリプルループ | O(n³) | 1T ops | 致命的 |
パフォーマンスの危険信号
| フラグ | 質問 | 理由 |
|---|---|---|
| ループ内のクエリ | 「バッチ処理できますか?」 | N+1 問題 |
| ページネーションなし | 「スケールするとどうなりますか?」 | メモリ/時間の爆発 |
| SELECT * | 「すべてのフィールドが必要ですか?」 | 帯域幅の浪費 |
| setInterval のクリーンアップなし | 「これをクリアするものは何ですか?」 | メモリリーク |
| JSX 内のインラインオブジェクト/関数 | 「新しい参照ですか?」 | 不要な再レンダリング |
| レンダリング内の Array.sort() | 「キャッシュされていますか?」 | レンダリングごとに実行されます |
気にしなくてもよい場合
すべてを最適化する必要はありません:
- 小規模なデータセット: 20 個のアイテムをページネーションしないでください
- まれな操作: 1 回限りの管理者スクリプトは遅くてもかまいません
- プロトタイプ段階: まずは動作させることを優先してください
- マイクロ最適化:
forとforEachではなく、アルゴリズムに焦点を当ててください
このゲートは、マイクロ最適化ではなく、明らかな問題を捕捉することを目的としています。
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Gate 4: Performance Review
"Code that works is step one. Code that scales is step two."
Purpose
This gate catches performance anti-patterns before they cause problems. The focus is on obvious issues, not micro-optimizations.
Gate Status
- PASS — No obvious performance issues
- WARNING — Issues found that could cause problems at scale
Gate Questions
Question 1: Scalability
"What happens when there are 10,000 items? 1,000,000?"
Looking for:
- Awareness of data growth
- Pagination for large datasets
- Efficient data structures
- No unnecessary loops
Question 2: Query Efficiency
"How many database queries does this operation make?"
Looking for:
- No N+1 queries
- Bulk operations where appropriate
- Indexes on queried columns
- Awareness of query cost
Question 3: Re-render Awareness (Frontend)
"When this state changes, what components re-render?"
Looking for:
- Awareness of render triggers
- Appropriate memoization
- State placement optimization
- No expensive computations in render
Performance Checklist
Database Operations
- [ ] No N+1 queries (queries inside loops)
- [ ] Pagination for list endpoints
- [ ] Indexes on frequently queried columns
- [ ] SELECT only needed columns (not SELECT *)
Frontend Rendering
- [ ] Expensive computations use useMemo
- [ ] Event handlers use useCallback where needed
- [ ] Large lists use virtualization
- [ ] Heavy components are lazy loaded
API & Network
- [ ] Response payloads are minimal
- [ ] Large data is paginated
- [ ] Caching headers where appropriate
- [ ] No redundant API calls
General
- [ ] No nested loops (O(n²)) without justification
- [ ] No blocking operations
- [ ] Cleanup of intervals/timeouts
- [ ] Reasonable memory usage
Response Templates
If PASS
✅ PERFORMANCE GATE: PASSED
Performance considerations look good:
- Data fetching is efficient
- No obvious N+1 patterns
- Appropriate pagination in place
Moving to the next gate...
If WARNING
⚠️ PERFORMANCE GATE: WARNING
Found [X] performance concerns:
**Issue 1: [N+1 Query / Inefficient Loop]**
Location: `file.ts:42`
Question: "This makes [N] queries. Can we batch into 1?"
**Issue 2: [Missing Pagination]**
Location: `file.ts:88`
Question: "What happens with 100,000 records?"
**Issue 3: [Expensive Render]**
Location: `Component.tsx:15`
Question: "Does this need to recalculate on every render?"
These may not matter now, but will become problems as the app grows.
Common Issues to Check
1. The N+1 Query Problem
❌ const users = await User.findAll();
for (const user of users) {
user.posts = await Post.findByUserId(user.id);
}
// 1 + N queries!
✅ const users = await User.findAll({
include: [{ model: Post }]
});
// 1 query with JOIN
2. Fetching Everything
❌ // Returns 10,000 users with 50 fields each
GET /api/users
✅ // Paginated with only needed fields
GET /api/users?page=1&limit=20&fields=id,name,email
3. Expensive Render Calculations
❌ function UserList({ users }) {
// Runs on every render
const sorted = users.sort((a, b) => a.name.localeCompare(b.name));
return <ul>{sorted.map(...)}</ul>;
}
✅ function UserList({ users }) {
const sorted = useMemo(
() => [...users].sort((a, b) => a.name.localeCompare(b.name)),
[users]
);
return <ul>{sorted.map(...)}</ul>;
}
4. Inline Functions Causing Re-renders
❌ function Parent() {
return <Child onClick={() => doSomething()} />;
// New function every render → Child re-renders
}
✅ function Parent() {
const handleClick = useCallback(() => doSomething(), []);
return <Child onClick={handleClick} />;
}
5. Missing Cleanup
❌ useEffect(() => {
const interval = setInterval(fetchData, 5000);
// Memory leak! Runs forever
}, []);
✅ useEffect(() => {
const interval = setInterval(fetchData, 5000);
return () => clearInterval(interval);
}, []);
Socratic Performance Questions
Instead of pointing out the fix, ask:
- "How many queries does this endpoint execute for 100 users?"
- "If I add 10,000 more items, what breaks?"
- "Does this array get re-sorted on every render?"
- "What clears this interval when the component unmounts?"
- "Do we need all 50 columns from this table?"
Big O Quick Reference
| Pattern | Complexity | 10,000 items | Concern Level |
|---|---|---|---|
| Map lookup | O(1) | 1 op | Fine |
| Single loop | O(n) | 10,000 ops | Usually fine |
| Nested loop | O(n²) | 100M ops | Warning |
| Triple loop | O(n³) | 1T ops | Critical |
Performance Red Flags
| Flag | Question | Why |
|---|---|---|
| Query in a loop | "Can we batch?" | N+1 problem |
| No pagination | "What at scale?" | Memory/time explosion |
| SELECT * | "Need all fields?" | Wasted bandwidth |
| setInterval no cleanup | "What clears this?" | Memory leak |
| Inline object/function in JSX | "New reference?" | Unnecessary re-renders |
| Array.sort() in render | "Cached?" | Runs every render |
When to NOT Worry
Not everything needs optimization:
- Small datasets: Don't paginate 20 items
- Rare operations: One-time admin scripts can be slow
- Prototype phase: Get it working first
- Micro-optimizations: Focus on algorithms, not
forvsforEach
The gate is about catching obvious issues, not micro-optimization.