analyze-performance

パフォーマンスボトルネックを特定し、最適化提案を提示

16 stars

Best use case

analyze-performance is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

パフォーマンスボトルネックを特定し、最適化提案を提示

Teams using analyze-performance should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/analyze-performance/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/backend/analyze-performance/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/analyze-performance/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How analyze-performance Compares

Feature / Agentanalyze-performanceStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

パフォーマンスボトルネックを特定し、最適化提案を提示

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# civicship-api パフォーマンス分析

パフォーマンスの**ボトルネック**を特定し、最適化提案を提示します。N+1問題、不要なクエリ、非効率なアルゴリズムを検出します。

## 使用方法

```bash
# ドメイン全体のパフォーマンス分析
/analyze-performance wallet

# 特定ファイルの分析
/analyze-performance src/application/domain/account/wallet/service.ts

# 全体のパフォーマンスレポート
/analyze-performance --all
```

**引数:**
- `$ARGUMENTS`: ドメイン名、ファイルパス、または `--all`

---

## パフォーマンス分析プロセス

### ステップ1: N+1問題の検出

ループ内のクエリ実行を検出:

```bash
# ループ内のawait検索
grep -A 5 "for.*of\|for.*in\|forEach\|map" src/application/domain/${DOMAIN}/**/*.ts | grep -B 3 "await.*find\|await.*query"

# DataLoaderの使用確認
grep -r "ctx.loaders" src/application/domain/${DOMAIN}/**/*.ts
```

**N+1問題レポート:**

```markdown
## N+1問題の検出

### 🔴 Critical: N+1問題あり

#### 問題1: UserResolver.wallets

**ファイル:** `src/application/domain/account/user/controller/resolver.ts:45`

**コード:**
\`\`\`typescript
User: {
  wallets: async (parent, _, ctx) => {
    // 全ユーザーに対してこのクエリが実行される(N+1)
    return await prisma.t_wallets.findMany({
      where: { userId: parent.id }
    });
  }
}
\`\`\`

**問題:**
- 100ユーザーを取得すると、100回のクエリが実行される
- レスポンスタイム: 5秒以上

**推奨修正:**
\`\`\`typescript
User: {
  wallets: (parent, _, ctx) => {
    // DataLoaderでバッチローディング
    return ctx.loaders.walletsByUserId.load(parent.id);
  }
}

// DataLoader定義
const walletsByUserIdLoader = new DataLoader(async (userIds) => {
  const wallets = await prisma.t_wallets.findMany({
    where: { userId: { in: userIds } }
  });
  // userIdごとにグループ化して返す
  return userIds.map(id => wallets.filter(w => w.userId === id));
});
\`\`\`

**効果:**
- クエリ数: 100回 → 1回
- レスポンスタイム: 5秒 → 50ms(100倍改善)

---

### ✅ 正しい実装例

#### Opportunity.community(DataLoader使用)

**ファイル:** `src/application/domain/experience/opportunity/controller/resolver.ts:30`

\`\`\`typescript
Opportunity: {
  community: (parent, _, ctx) => {
    return ctx.loaders.community.load(parent.communityId);
  }
}
\`\`\`

**評価:** N+1問題なし
```

---

### ステップ2: 不要なクエリの検出

同じデータを複数回取得している箇所を検出:

```bash
# 同じクエリが複数回実行されている可能性
grep -A 3 "findUnique\|findFirst" src/application/domain/${DOMAIN}/**/*.ts | sort | uniq -c | sort -rn
```

**不要クエリレポート:**

```markdown
## 不要なクエリ

### 問題1: 重複したウォレット取得

**ファイル:** `src/application/domain/transaction/point-transfer/service.ts:120`

**コード:**
\`\`\`typescript
async transferPoints(ctx, input, tx) {
  // ウォレットを2回取得(無駄)
  const fromWallet = await this.walletRepo.findById(ctx, input.fromWalletId, tx);
  const toWallet = await this.walletRepo.findById(ctx, input.toWalletId, tx);

  // バリデーション後、再度取得(無駄)
  const fromWalletAgain = await this.walletRepo.findById(ctx, input.fromWalletId, tx);

  // ...
}
\`\`\`

**推奨修正:**
\`\`\`typescript
async transferPoints(ctx, input, tx) {
  // 1回だけ取得
  const [fromWallet, toWallet] = await Promise.all([
    this.walletRepo.findById(ctx, input.fromWalletId, tx),
    this.walletRepo.findById(ctx, input.toWalletId, tx)
  ]);

  // 再取得せず、メモリ上のデータを使用
  // ...
}
\`\`\`

**効果:**
- クエリ数: 3回 → 2回
- レスポンスタイム: 15ms → 10ms
```

---

### ステップ3: SELECT句の最適化

必要以上のカラムを取得している箇所を検出:

```bash
# SELECT * の使用箇所
grep -r "prisma.*\.findMany\|prisma.*\.findUnique" src/application/domain/${DOMAIN}/**/*.ts | grep -v "select:"
```

**SELECT最適化レポート:**

```markdown
## SELECT句の最適化

### 問題1: 全カラム取得

**ファイル:** `src/application/domain/account/wallet/data/repository.ts:50`

**コード:**
\`\`\`typescript
async findById(ctx, id, tx) {
  // 全カラムを取得(無駄が多い)
  return tx.t_wallets.findUnique({ where: { id } });
}
\`\`\`

**問題:**
- 不要なカラム(例: `metadata`, `internalNotes`)も取得
- ネットワーク転送量が増加
- メモリ使用量が増加

**推奨修正:**
\`\`\`typescript
async findById(ctx, id, tx) {
  // 必要なカラムのみ取得
  return tx.t_wallets.findUnique({
    where: { id },
    select: {
      id: true,
      userId: true,
      balance: true,
      expiresAt: true,
      createdAt: true,
      updatedAt: true
    }
  });
}
\`\`\`

**効果:**
- データ転送量: 1KB → 200B(80%削減)
- メモリ使用量: 削減
```

---

### ステップ4: インデックスの確認

データベースインデックスの不足を検出:

```bash
# WHERE句で使用されているカラムを抽出
grep -r "where:" src/application/domain/${DOMAIN}/data/repository.ts | grep -o "{.*}" | sort | uniq

# Prismaスキーマのインデックス確認
grep -A 10 "model t_wallets" prisma/schema.prisma | grep "@@index"
```

**インデックスレポート:**

```markdown
## インデックス分析

### 推奨: インデックス追加

#### インデックス1: t_wallets.expiresAt

**使用箇所:**
- バッチ処理: 有効期限切れポイントの検索
- クエリ: `WHERE expiresAt < NOW()`

**現状:** インデックスなし

**推奨:**
\`\`\`prisma
model t_wallets {
  // ...
  @@index([expiresAt])
}
\`\`\`

**効果:**
- クエリ時間: 500ms → 10ms(50倍改善)

---

#### インデックス2: t_wallets.userId + createdAt

**使用箇所:**
- ウォレット一覧の取得(ユーザーID + 作成日でソート)

**現状:** userId のみインデックス

**推奨:**
\`\`\`prisma
model t_wallets {
  // ...
  @@index([userId, createdAt])
}
\`\`\`

**効果:**
- ソートパフォーマンス向上
```

---

### ステップ5: 非効率なアルゴリズムの検出

計算量が大きいコードを検出:

```markdown
## アルゴリズム分析

### 問題1: ネストループ(O(N²))

**ファイル:** `src/application/domain/reward/utility/service.ts:80`

**コード:**
\`\`\`typescript
async findMatchingUtilities(ctx, userId) {
  const utilities = await this.repo.findAll(ctx);  // 1,000件
  const userSkills = await this.userSkillRepo.findByUserId(ctx, userId);  // 10件

  // O(N * M) = O(10,000)
  return utilities.filter(utility => {
    return userSkills.some(skill => {
      return utility.requiredSkills.includes(skill.skillId);
    });
  });
}
\`\`\`

**問題:**
- 計算量: O(N * M * K)
- 処理時間: 100ms以上

**推奨修正:**
\`\`\`typescript
async findMatchingUtilities(ctx, userId) {
  const userSkills = await this.userSkillRepo.findByUserId(ctx, userId);
  const skillIds = userSkills.map(s => s.skillId);

  // データベースで絞り込み(O(N))
  return this.repo.findBySkills(ctx, skillIds);
}

// Repository
async findBySkills(ctx, skillIds) {
  return ctx.issuer.public(ctx, (tx) =>
    tx.t_utilities.findMany({
      where: {
        requiredSkills: { hasSome: skillIds }
      }
    })
  );
}
\`\`\`

**効果:**
- 計算量: O(N) に改善
- 処理時間: 100ms → 10ms
```

---

### ステップ6: キャッシュの提案

頻繁にアクセスされるデータのキャッシュを提案:

```markdown
## キャッシュ戦略

### 提案1: ウォレット残高のキャッシュ

**現状:**
- 残高取得クエリ: 毎回データベースアクセス
- 頻度: 100回/秒

**提案:**
\`\`\`typescript
// Redis キャッシュ
import { Redis } from 'ioredis';
const redis = new Redis();

async findById(ctx, id) {
  // キャッシュ確認
  const cached = await redis.get(\`wallet:\${id}\`);
  if (cached) return JSON.parse(cached);

  // データベースから取得
  const wallet = await this.repo.findById(ctx, id);

  // キャッシュに保存(TTL: 60秒)
  await redis.setex(\`wallet:\${id}\`, 60, JSON.stringify(wallet));

  return wallet;
}
\`\`\`

**効果:**
- データベース負荷: 100回/秒 → 2回/秒(98%削減)
- レスポンスタイム: 5ms → 0.5ms

**注意:**
- キャッシュ無効化のタイミング
- データ整合性の考慮
```

---

### ステップ7: バッチ処理の最適化

バッチ処理のパフォーマンス改善:

```markdown
## バッチ処理の最適化

### 問題1: 1件ずつ処理

**ファイル:** `scripts/expire-points.ts`

**コード:**
\`\`\`typescript
async expirePoints() {
  const expiredWallets = await prisma.t_wallets.findMany({
    where: { expiresAt: { lt: new Date() } }
  });

  // 1件ずつ処理(遅い)
  for (const wallet of expiredWallets) {
    await prisma.t_wallets.update({
      where: { id: wallet.id },
      data: { balance: 0 }
    });
  }
}
\`\`\`

**推奨修正:**
\`\`\`typescript
async expirePoints() {
  // 一括更新(速い)
  await prisma.t_wallets.updateMany({
    where: { expiresAt: { lt: new Date() } },
    data: { balance: 0 }
  });
}
\`\`\`

**効果:**
- 処理時間: 1,000件で 10秒 → 0.5秒(20倍改善)
```

---

### ステップ8: パフォーマンスレポート生成

```markdown
# パフォーマンス分析レポート

**対象:** Walletドメイン
**分析日:** 2026-01-15

---

## エグゼクティブサマリー

### 総合評価

**パフォーマンススコア:** 65 / 100 🟡 改善余地あり

### 検出された問題

- **Critical:** 2件(N+1問題)
- **High:** 3件(不要クエリ、インデックス不足)
- **Medium:** 5件(非効率なアルゴリズム)

### 推定改善効果

| 項目 | 現状 | 改善後 | 効果 |
|------|------|--------|------|
| レスポンスタイム | 500ms | 50ms | 10倍 |
| クエリ数 | 100回/リクエスト | 5回/リクエスト | 95%削減 |
| データベース負荷 | 100% | 20% | 80%削減 |

---

## 優先度別の改善提案

### 🔴 P0: 即座に実施(Critical)

| # | 問題 | 改善内容 | 工数 | 効果 |
|---|------|---------|------|------|
| 1 | N+1問題(UserResolver.wallets) | DataLoader導入 | 2h | レスポンスタイム100倍改善 |
| 2 | インデックス不足(expiresAt) | インデックス追加 | 0.5h | クエリ50倍高速化 |

**Total:** 2.5時間

---

### 🟡 P1: 2週間以内に実施(High)

| # | 問題 | 改善内容 | 工数 | 効果 |
|---|------|---------|------|------|
| 3 | 重複クエリ | リファクタリング | 1h | クエリ数30%削減 |
| 4 | SELECT * 使用 | select句最適化 | 1.5h | 転送量80%削減 |
| 5 | 非効率アルゴリズム | データベースで絞り込み | 3h | 処理時間10倍改善 |

**Total:** 5.5時間

---

### 🟢 P2: 1ヶ月以内に実施(Medium)

| # | 問題 | 改善内容 | 工数 | 効果 |
|---|------|---------|------|------|
| 6-10 | バッチ処理最適化など | 一括更新、キャッシュ導入 | 8h | 全体最適化 |

**Total:** 8時間

---

## 実装計画

### Week 1: Critical対応
- Day 1-2: DataLoader導入
- Day 3: インデックス追加
- Day 4: テスト・検証
- Day 5: 本番デプロイ

### Week 2-3: High対応
- 重複クエリ削減
- SELECT句最適化
- アルゴリズム改善

### Month 2: Medium対応
- キャッシュ導入
- バッチ処理最適化

---

## 承認

- [ ] テックリード
- [ ] DevOpsリード
```

---

## 活用例

### 例1: ドメイン全体の分析

```bash
/analyze-performance wallet
```

**出力:**
- N+1問題の検出
- 最適化提案
- 優先度付き改善計画

---

### 例2: PRの パフォーマンスレビュー

```bash
/analyze-performance --pr 123
```

**出力:**
- 変更によるパフォーマンス影響
- 新たに導入されたボトルネック

---

## 参考資料

- [Prisma Performance Best Practices](https://www.prisma.io/docs/guides/performance-and-optimization)
- [DataLoader Documentation](https://github.com/graphql/dataloader)
- [Database Indexing Guide](https://www.postgresql.org/docs/current/indexes.html)

Related Skills

excel-field-analyzer

16
from diegosouzapw/awesome-omni-skill

分析Excel/CSV字段结构,AI自动生成中英文映射,验证翻译质量,输出统计报告。用于电子表格分析、数据字典创建、字段映射场景。

analyze-us-bank-credit-deposit-decoupling

16
from diegosouzapw/awesome-omni-skill

分析銀行貸款與存款之間的「信貸創造脫鉤」現象,追蹤存款的絕對收縮與回升軌跡,用以辨識聯準會緊縮政策在銀行體系內部的真實傳導效果。

analyze-silver-miner-metal-ratio

16
from diegosouzapw/awesome-omni-skill

以「銀礦股價格 ÷ 白銀價格」的相對比率衡量礦業股板塊相對於金屬本體的估值區間(偏貴/偏便宜),並用歷史分位數與類比區間推導「底部/頂部」訊號與情境推演。

analyze-jgb-insurer-superlong-flow

16
from diegosouzapw/awesome-omni-skill

從日本保險公司對超長期(10年以上)JGB 的淨買賣時間序列,自動產出「本月是否創紀錄淨賣出、連續淨賣出月數、期間累積淨賣出」等結論。

analyze-japan-debt-service-tax-burden

16
from diegosouzapw/awesome-omni-skill

以日本公債殖利率變化為觸發,量化「政府利息支出 / 稅收」負擔(含情境壓力測試),並判斷是否進入債務利息螺旋風險區。

analyze-investment-clock-rotation

16
from diegosouzapw/awesome-omni-skill

把「獲利成長 × 財務狀況(金融環境)」映射成「投資時鐘」,判斷目前落在哪個象限、近期是順時針還是逆時針旋轉、以及相對於上一輪循環的位置差異。

analyze-copper-supply-concentration-risk

16
from diegosouzapw/awesome-omni-skill

用公開資料量化「銅供應是否過度集中、主要產地是否結構性衰退、替代增量是否依賴少數國家」,並輸出可行的中期供應風險結論與情境推演。

analyze-copper-stock-resilience-dependency

16
from diegosouzapw/awesome-omni-skill

用跨資產訊號(全球股市韌性 + 中國利率環境)評估銅價能否突破關卡或進入「回補/回踩」到支撐的機率與路徑。

analyze-agent-overlap

16
from diegosouzapw/awesome-omni-skill

Analyzes existing agents, skills, prompts, and instructions to identify overlaps, redundancies, and conflicts. Works with GitHub Copilot, Claude Code, Codex, OpenCode, and other providers. Use before creating new customization files to avoid duplication, when consolidating agents, or when troubleshooting conflicting behaviors.

ab-testing-analyzer

16
from diegosouzapw/awesome-omni-skill

全面的AB测试分析工具,支持实验设计、统计检验、用户分群分析和可视化报告生成。用于分析产品改版、营销活动、功能优化等AB测试结果,提供统计显著性检验和深度洞察。

32-analyze-verify-150

16
from diegosouzapw/awesome-omni-skill

[32] ANALYZE. Ensure every critical claim has verifiable evidence with confidence levels. Each fact must have source + confidence percentage. If confidence <85%, enter Loop150 to find more sources. Use for critical decisions, factual claims, legal/compliance work, or any situation where unverified claims are dangerous.

video-analyzer

16
from diegosouzapw/awesome-omni-skill

鏅鸿兘鍒嗘瀽 Bilibili/YouTube/鏈湴瑙嗛锛岀敓鎴愯浆鍐欍€佽瘎浼板拰鎬荤粨銆傛敮鎸佸叧閿抚鎴浘鑷姩宓屽叆銆?