performance-fundamentals
ループ処理、データ取得、画面描画、データベース処理など負荷の高い処理を見直し、N+1問題や無駄な再描画、メモリリーク、拡張性の問題点などを自動で特定し改善を支援するSkill。
📜 元の英語説明(参考)
Auto-invoke when reviewing loops, data fetching, rendering, database queries, or resource-intensive operations. Identifies N+1 queries, unnecessary re-renders, memory leaks, and scalability issues.
🇯🇵 日本人クリエイター向け解説
ループ処理、データ取得、画面描画、データベース処理など負荷の高い処理を見直し、N+1問題や無駄な再描画、メモリリーク、拡張性の問題点などを自動で特定し改善を支援するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o performance-fundamentals.zip https://jpskill.com/download/18286.zip && unzip -o performance-fundamentals.zip && rm performance-fundamentals.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/18286.zip -OutFile "$d\performance-fundamentals.zip"; Expand-Archive "$d\performance-fundamentals.zip" -DestinationPath $d -Force; ri "$d\performance-fundamentals.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
performance-fundamentals.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
performance-fundamentalsフォルダができる - 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 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
パフォーマンスの基礎レビュー
「時期尚早な最適化は諸悪の根源である。しかし、成熟した無知はもっと悪い。」
適用するタイミング
以下のレビュー時にこのスキルを有効化してください。
- データベースクエリ(特にループ内)
- React/Vue のレンダリングロジック
- API のレスポンスペイロード
- データ変換
- ファイル操作
- キャッシュに関する決定
レビューチェックリスト
データベースのパフォーマンス
- [ ] N+1 クエリがないか: 関連レコードはループではなく、まとめてフェッチされていますか?
- [ ] インデックス: 頻繁にクエリされるフィールドにインデックスは設定されていますか?
- [ ] ページネーション: リストエンドポイントは結果をページネーションしていますか?
- [ ] 必要なフィールドのみを選択: 不必要にレコード全体をフェッチしていませんか?
フロントエンドのパフォーマンス
- [ ] メモ化: コストの高い計算はキャッシュされていますか?
- [ ] 再レンダリングの防止: ステートの変更は不必要な再レンダリングを引き起こしませんか?
- [ ] バンドルサイズ: 重いライブラリは遅延ロードされていますか?
- [ ] 画像の最適化: 画像は適切なサイズと形式になっていますか?
API のパフォーマンス
- [ ] レスポンスサイズ: ペイロードは最小限ですか?
- [ ] 圧縮: gzip/brotli は有効になっていますか?
- [ ] キャッシュヘッダー: キャッシュ可能なレスポンスはマークされていますか?
- [ ] 非同期処理: 時間のかかる操作はキューに入れられていますか?
メモリとリソース
- [ ] クリーンアップ: サブスクリプション/タイマーはクリーンアップされていますか?
- [ ] メモリリーク: イベントリスナーは削除されていますか?
- [ ] コネクションプーリング: DB コネクションは再利用されていますか?
よくある間違い(アンチパターン)
1. N+1 クエリ問題
❌ const users = await User.findAll();
for (const user of users) {
user.posts = await Post.findByUserId(user.id); // N クエリ!
}
✅ const users = await User.findAll({
include: [{ model: Post }] // JOIN を使用した 1 クエリ
});
2. 不必要な再レンダリング
❌ function Parent() {
const handleClick = () => {}; // レンダリングごとに新しい関数
return <Child onClick={handleClick} />;
}
✅ function Parent() {
const handleClick = useCallback(() => {}, []);
return <Child onClick={handleClick} />;
}
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. すべてをフェッチする
❌ GET /api/users → すべてのフィールドを持つ 10,000 人のユーザーを返す
✅ GET /api/users?page=1&limit=20&fields=id,name,email
5. クリーンアップの欠如
❌ useEffect(() => {
const interval = setInterval(fetchData, 5000);
// クリーンアップなし! 永遠に実行されます。
}, []);
✅ useEffect(() => {
const interval = setInterval(fetchData, 5000);
return () => clearInterval(interval);
}, []);
ソクラテス式質問
ジュニアに答えを与える代わりに、これらの質問をしてください。
- スケール: 「10,000 個のアイテムがある場合はどうなりますか? 1,000,000 個の場合は?」
- クエリ: 「この操作はデータベースクエリを何回実行しますか?」
- 再レンダリング: 「このステートが変更されたとき、どのコンポーネントが再レンダリングされますか?」
- メモリ: 「不要になった後も参照を保持しているものはありますか?」
- ペイロード: 「クライアントはこのデータのすべてを必要としますか?」
Big O クイックリファレンス
| パターン | 複雑性 | 例 | 10,000 個のアイテムの場合 |
|---|---|---|---|
| 直接ルックアップ | O(1) | map.get(key) |
1 op |
| 単一ループ | O(n) | array.find() |
10,000 ops |
| ネストされたループ | O(n²) | for i { for j } |
100,000,000 ops |
| ソート | O(n log n) | array.sort() |
~130,000 ops |
パフォーマンスタゲット
| メトリクス | ターゲット | 測定方法 |
|---|---|---|
| Time to First Byte (TTFB) | < 600ms | DevTools Network |
| Largest Contentful Paint (LCP) | < 2.5s | Lighthouse |
| First Input Delay (FID) | < 100ms | Lighthouse |
| Cumulative Layout Shift (CLS) | < 0.1 | Lighthouse |
| API Response Time | < 200ms (p95) | サーバーメトリクス |
指摘すべき危険信号
| フラグ | 質問 |
|---|---|
| ループ内のクエリ | 「これを 1 つのクエリにまとめることはできますか?」 |
| ページネーションなし | 「100,000 件のレコードがある場合はどうなりますか?」 |
SELECT * |
「これらのフィールドはすべて必要ですか?」 |
| localStorage の大きな JSON | 「これはページロードを遅くしますか?」 |
| JSX のインライン関数 | 「これはレンダリングごとに新しい関数を作成しますか?」 |
| クリーンアップなしの setInterval | 「コンポーネントがアンマウントされたときに、これは何をクリアしますか?」 |
| 同期的なファイル操作 | 「これは非同期であるべきですか?」 |
| ローディング状態がない | 「待機中にユーザーには何が表示されますか?」 |
クイックウィン
- 頻繁にクエリされる DB カラムにインデックスを追加する
- すべてのリストエンドポイントをページネーションする
- 画面外のコンテンツを遅延ロードする
- API レスポンスを圧縮する
- useMemo でコストの高い計算をキャッシュする
- 検索入力をデバウンスする
- 長いリストを仮想化する (react-window)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
Performance Fundamentals Review
"Premature optimization is the root of all evil, but mature ignorance is worse."
When to Apply
Activate this skill when reviewing:
- Database queries (especially in loops)
- React/Vue render logic
- API response payloads
- Data transformations
- File operations
- Caching decisions
Review Checklist
Database Performance
- [ ] No N+1 queries: Are related records fetched in bulk, not loops?
- [ ] Indexes: Are frequently queried fields indexed?
- [ ] Pagination: Do list endpoints paginate results?
- [ ] Select only needed fields: Are we fetching entire records unnecessarily?
Frontend Performance
- [ ] Memoization: Are expensive computations cached?
- [ ] Re-render prevention: Will state changes cause unnecessary re-renders?
- [ ] Bundle size: Are heavy libraries lazy-loaded?
- [ ] Image optimization: Are images properly sized and formatted?
API Performance
- [ ] Response size: Is the payload minimal?
- [ ] Compression: Is gzip/brotli enabled?
- [ ] Caching headers: Are cacheable responses marked?
- [ ] Async processing: Are slow operations queued?
Memory & Resources
- [ ] Cleanup: Are subscriptions/timers cleaned up?
- [ ] Memory leaks: Are event listeners removed?
- [ ] Connection pooling: Are DB connections reused?
Common Mistakes (Anti-Patterns)
1. The N+1 Query Problem
❌ const users = await User.findAll();
for (const user of users) {
user.posts = await Post.findByUserId(user.id); // N queries!
}
✅ const users = await User.findAll({
include: [{ model: Post }] // 1 query with JOIN
});
2. Unnecessary Re-renders
❌ function Parent() {
const handleClick = () => {}; // New function every render
return <Child onClick={handleClick} />;
}
✅ function Parent() {
const handleClick = useCallback(() => {}, []);
return <Child onClick={handleClick} />;
}
3. Computing in Render
❌ 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. Fetching Everything
❌ GET /api/users → returns 10,000 users with all fields
✅ GET /api/users?page=1&limit=20&fields=id,name,email
5. Missing Cleanup
❌ useEffect(() => {
const interval = setInterval(fetchData, 5000);
// No cleanup! Runs forever.
}, []);
✅ useEffect(() => {
const interval = setInterval(fetchData, 5000);
return () => clearInterval(interval);
}, []);
Socratic Questions
Ask the junior these questions instead of giving answers:
- Scale: "What happens when there are 10,000 items? 1,000,000?"
- Queries: "How many database queries does this operation make?"
- Re-renders: "When this state changes, what components re-render?"
- Memory: "Is anything holding a reference after it's no longer needed?"
- Payload: "Does the client need ALL of this data?"
Big O Quick Reference
| Pattern | Complexity | Example | At 10,000 items |
|---|---|---|---|
| Direct lookup | O(1) | map.get(key) |
1 op |
| Single loop | O(n) | array.find() |
10,000 ops |
| Nested loops | O(n²) | for i { for j } |
100,000,000 ops |
| Sort | O(n log n) | array.sort() |
~130,000 ops |
Performance Targets
| Metric | Target | Measure With |
|---|---|---|
| Time to First Byte (TTFB) | < 600ms | DevTools Network |
| Largest Contentful Paint (LCP) | < 2.5s | Lighthouse |
| First Input Delay (FID) | < 100ms | Lighthouse |
| Cumulative Layout Shift (CLS) | < 0.1 | Lighthouse |
| API Response Time | < 200ms (p95) | Server metrics |
Red Flags to Call Out
| Flag | Question to Ask |
|---|---|
| Query inside a loop | "Can we batch this into one query?" |
| No pagination | "What if there are 100,000 records?" |
SELECT * |
"Do we need all these fields?" |
| Large JSON in localStorage | "Will this slow down page load?" |
| Inline function in JSX | "Does this create a new function every render?" |
| setInterval without cleanup | "What clears this when the component unmounts?" |
| Synchronous file operations | "Should this be async?" |
| No loading states | "What does the user see while waiting?" |
Quick Wins
- Add indexes to frequently queried DB columns
- Paginate all list endpoints
- Lazy load below-the-fold content
- Compress API responses
- Cache expensive computations with useMemo
- Debounce search inputs
- Virtualize long lists (react-window)