ベストプラクティス

AI支援によるパフォーマンス最適化

AIを使用してコードのパフォーマンスボトルネックを特定して修正します。より高速で効率的なアプリケーションのための実践的なテクニックを学びます。

C
CCJK Team2025年1月5日
13 分で読めます
1,335 回閲覧
AI支援によるパフォーマンス最適化

AI支援によるパフォーマンス最適化

パフォーマンスの問題は、診断に時間がかかり、見つけにくいことがあります。AIアシスタントは、コードパターンの分析、ボトルネックの特定、最適化の提案に優れています。このガイドでは、パフォーマンス作業にAIを活用する方法を示します。

AI支援パフォーマンス分析

パフォーマンスレビューのリクエスト

あなた:この関数のパフォーマンス問題を分析してください:

function processOrders(orders) {
  const results = [];
  for (const order of orders) {
    const user = users.find(u => u.id === order.userId);
    const products = order.items.map(item =>
      products.find(p => p.id === item.productId)
    );
    results.push({ order, user, products });
  }
  return results;
}

Claude:いくつかのパフォーマンス問題を特定しました:

1. **O(n²)の計算量** - ループ内の`users.find()`
2. **O(n³)の計算量** - map内のネストされた`products.find()`
3. **早期終了なし** - 制限が必要でもすべての注文を処理

O(n)の計算量を持つ最適化されたバージョンは以下です...

/perf スキルの使用

hljs bash
# ファイルを分析 /perf src/services/orderService.js # 特定のフォーカスで分析 /perf --focus memory src/utils/dataProcessor.js # パフォーマンスレポートを生成 /perf --report src/

一般的なパフォーマンスパターン

パターン1:ループの最適化

最適化前(O(n²)):

hljs javascript
function findMatches(items, targets) { return items.filter(item => targets.includes(item.id) // 各アイテムに対してO(n) ); }

最適化後(O(n)):

hljs javascript
function findMatches(items, targets) { const targetSet = new Set(targets); // 一度だけO(n) return items.filter(item => targetSet.has(item.id) // 各アイテムに対してO(1) ); }

パターン2:メモ化

最適化前:

hljs javascript
function fibonacci(n) { if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2); } // fibonacci(40)は約1秒かかる

最適化後:

hljs javascript
function fibonacci(n, memo = {}) { if (n in memo) return memo[n]; if (n <= 1) return n; memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo); return memo[n]; } // fibonacci(40)は約0.001msかかる

パターン3:遅延読み込み

最適化前:

hljs javascript
// すべてを事前に読み込む import { Chart, Table, Form, Modal, DatePicker } from 'heavy-ui-lib';

最適化後:

hljs javascript
// 必要なときだけ読み込む const Chart = lazy(() => import('heavy-ui-lib/Chart')); const Table = lazy(() => import('heavy-ui-lib/Table'));

パターン4:データベースクエリの最適化

最適化前(N+1問題):

hljs javascript
const orders = await Order.findAll(); for (const order of orders) { order.user = await User.findById(order.userId); // Nクエリ }

最適化後(Eager Loading):

hljs javascript
const orders = await Order.findAll({ include: [{ model: User, as: 'user' }] // JOINを使用した1クエリ });

Reactパフォーマンス最適化

再レンダリング問題の特定

Claudeにコンポーネントのレンダリングを分析してもらう:

あなた:このコンポーネントが過度に再レンダリングされる理由は?

function ProductList({ products, onSelect }) {
  return (
    <ul>
      {products.map(product => (
        <li key={product.id} onClick={() => onSelect(product)}>
          {product.name}
        </li>
      ))}
    </ul>
  );
}

Claude:再レンダリングの問題を特定しました:

1. **インラインアロー関数**:各レンダリングで新しい関数を作成
2. **メモ化なし**:productsが変更されていなくても再レンダリング

最適化されたバージョン:
hljs typescript
import { memo, useCallback } from 'react'; const ProductList = memo(({ products, onSelect }) => { return ( <ul> {products.map(product => ( <ProductItem key={product.id} product={product} onSelect={onSelect} /> ))} </ul> ); }); const ProductItem = memo(({ product, onSelect }) => { const handleClick = useCallback(() => { onSelect(product); }, [product, onSelect]); return ( <li onClick={handleClick}> {product.name} </li> ); });

useMemoとuseCallbackの使用

hljs typescript
// ❌ 悪い例:毎回再計算 function ExpensiveComponent({ items }) { const total = items.reduce((sum, item) => sum + item.price, 0); const average = total / items.length; return <div>平均: {average}</div>; } // ✅ 良い例:メモ化された計算 function ExpensiveComponent({ items }) { const total = useMemo( () => items.reduce((sum, item) => sum + item.price, 0), [items] ); const average = useMemo( () => total / items.length, [total, items.length] ); return <div>平均: {average}</div>; }

仮想化の実装

hljs typescript
import { FixedSizeList } from 'react-window'; // ❌ 悪い例:10,000アイテムをすべてレンダリング function LargeList({ items }) { return ( <div> {items.map(item => ( <div key={item.id}>{item.name}</div> ))} </div> ); } // ✅ 良い例:表示されているアイテムのみレンダリング function LargeList({ items }) { return ( <FixedSizeList height={600} itemCount={items.length} itemSize={50} width="100%" > {({ index, style }) => ( <div style={style}>{items[index].name}</div> )} </FixedSizeList> ); }

バックエンドパフォーマンス最適化

データベースインデックス

hljs sql
-- ❌ 悪い例:インデックスなし SELECT * FROM users WHERE email = 'user@example.com'; -- 実行時間:500ms(100万行) -- ✅ 良い例:インデックス付き CREATE INDEX idx_users_email ON users(email); SELECT * FROM users WHERE email = 'user@example.com'; -- 実行時間:5ms

クエリの最適化

hljs javascript
// ❌ 悪い例:すべてのフィールドを選択 const users = await db.query('SELECT * FROM users'); // ✅ 良い例:必要なフィールドのみ選択 const users = await db.query('SELECT id, name, email FROM users'); // ❌ 悪い例:ループ内でクエリ for (const userId of userIds) { const user = await User.findById(userId); users.push(user); } // ✅ 良い例:単一クエリ const users = await User.findAll({ where: { id: { [Op.in]: userIds } } });

キャッシング戦略

hljs typescript
import Redis from 'ioredis'; const redis = new Redis(); // シンプルなキャッシング async function getUser(id: string) { // キャッシュを確認 const cached = await redis.get(`user:${id}`); if (cached) return JSON.parse(cached); // データベースから取得 const user = await User.findById(id); // キャッシュに保存(1時間) await redis.setex(`user:${id}`, 3600, JSON.stringify(user)); return user; } // キャッシュ無効化 async function updateUser(id: string, data: any) { const user = await User.update(id, data); // キャッシュを無効化 await redis.del(`user:${id}`); return user; }

接続プーリング

hljs typescript
// ❌ 悪い例:各リクエストで新しい接続 async function query(sql: string) { const connection = await mysql.createConnection(config); const result = await connection.query(sql); await connection.end(); return result; } // ✅ 良い例:接続プール const pool = mysql.createPool({ host: 'localhost', user: 'root', database: 'mydb', connectionLimit: 10, queueLimit: 0 }); async function query(sql: string) { const connection = await pool.getConnection(); try { const result = await connection.query(sql); return result; } finally { connection.release(); } }

フロントエンドパフォーマンス最適化

バンドルサイズの削減

hljs bash
# バンドルサイズを分析 npm run build -- --analyze # 未使用のコードを削除 npm install -g depcheck depcheck # Tree shakingを有効化 # webpack.config.js module.exports = { mode: 'production', optimization: { usedExports: true, sideEffects: false } };

コード分割

hljs typescript
// ❌ 悪い例:すべてを1つのバンドルに import Dashboard from './Dashboard'; import Analytics from './Analytics'; import Settings from './Settings'; // ✅ 良い例:ルートベースのコード分割 const Dashboard = lazy(() => import('./Dashboard')); const Analytics = lazy(() => import('./Analytics')); const Settings = lazy(() => import('./Settings')); function App() { return ( <Suspense fallback={<Loading />}> <Routes> <Route path="/dashboard" element={<Dashboard />} /> <Route path="/analytics" element={<Analytics />} /> <Route path="/settings" element={<Settings />} /> </Routes> </Suspense> ); }

画像の最適化

hljs typescript
// ❌ 悪い例:最適化されていない画像 <img src="/images/hero.jpg" alt="Hero" /> // ✅ 良い例:最適化された画像 import Image from 'next/image'; <Image src="/images/hero.jpg" alt="Hero" width={1200} height={600} loading="lazy" placeholder="blur" />

リソースのプリロード

hljs html
<!-- 重要なリソースをプリロード --> <link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin> <link rel="preload" href="/critical.css" as="style"> <!-- DNSプリフェッチ --> <link rel="dns-prefetch" href="https://api.example.com"> <!-- プリコネクト --> <link rel="preconnect" href="https://cdn.example.com">

パフォーマンス測定

Web Vitalsの監視

hljs typescript
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals'; function sendToAnalytics(metric: any) { // 分析サービスに送信 console.log(metric); } getCLS(sendToAnalytics); // Cumulative Layout Shift getFID(sendToAnalytics); // First Input Delay getFCP(sendToAnalytics); // First Contentful Paint getLCP(sendToAnalytics); // Largest Contentful Paint getTTFB(sendToAnalytics); // Time to First Byte

カスタムパフォーマンス測定

hljs typescript
// パフォーマンスマーカー performance.mark('data-fetch-start'); await fetchData(); performance.mark('data-fetch-end'); performance.measure('data-fetch', 'data-fetch-start', 'data-fetch-end'); const measure = performance.getEntriesByName('data-fetch')[0]; console.log(`データ取得時間: ${measure.duration}ms`); // パフォーマンスオブザーバー const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { console.log(`${entry.name}: ${entry.duration}ms`); } }); observer.observe({ entryTypes: ['measure', 'navigation'] });

プロファイリング

hljs typescript
// React Profilerを使用 import { Profiler } from 'react'; function onRenderCallback( id: string, phase: 'mount' | 'update', actualDuration: number, baseDuration: number, startTime: number, commitTime: number ) { console.log(`${id} (${phase}): ${actualDuration}ms`); } function App() { return ( <Profiler id="App" onRender={onRenderCallback}> <Dashboard /> </Profiler> ); }

AIを使用したパフォーマンス最適化

パフォーマンスレビューのリクエスト

あなた:このコンポーネントのパフォーマンスを最適化してください:

[コードを貼り付け]

以下に焦点を当ててください:
1. 不要な再レンダリング
2. メモリリーク
3. 計算量
4. バンドルサイズへの影響

Claude:分析と最適化を提供します...

ボトルネックの特定

あなた:このアプリケーションが遅い理由を特定してください。
プロファイリングデータ:
[パフォーマンスデータを貼り付け]

Claude:ボトルネックを分析します...

最適化の提案

あなた:このデータ処理パイプラインを最適化する方法を提案してください:

[コードを貼り付け]

制約:
- メモリ使用量を最小限に
- リアルタイム処理が必要
- 既存のAPIを維持

Claude:最適化戦略を提供します...

パフォーマンスベストプラクティス

1. 早期最適化を避ける

まず動作させ、次に測定し、その後最適化します。

2. 測定してから最適化

推測ではなく、データに基づいて最適化します。

3. 低い果実から始める

最大の影響を与える最適化に焦点を当てます。

4. ユーザー体験を優先

技術的なメトリクスよりもユーザーが感じるパフォーマンスを重視します。

5. 継続的に監視

パフォーマンスは一度限りのタスクではなく、継続的なプロセスです。

パフォーマンスチェックリスト

フロントエンド

  • バンドルサイズを最小化
  • コード分割を実装
  • 画像を最適化
  • 遅延読み込みを使用
  • 不要な再レンダリングを削減
  • Web Vitalsを監視

バックエンド

  • データベースクエリを最適化
  • インデックスを追加
  • キャッシングを実装
  • 接続プーリングを使用
  • N+1問題を解決
  • APIレスポンスを圧縮

一般

  • パフォーマンステストを実行
  • プロファイリングを実施
  • ボトルネックを特定
  • 最適化を測定
  • 継続的に監視
  • ドキュメント化

まとめ

パフォーマンス最適化は、測定、分析、改善の継続的なサイクルです。AIアシスタントは、ボトルネックの特定、最適化の提案、ベストプラクティスの適用に役立ちます。

効果的なパフォーマンス最適化のために:

  • 測定してから最適化
  • 最大の影響を与える問題に焦点を当てる
  • AIを使用してパターンを特定
  • 継続的に監視
  • ユーザー体験を優先

次へチームコラボレーションでCCJKをチームで効果的に使用する方法を学びます。

よくある質問

パフォーマンス最適化はいつ行うべきですか?

パフォーマンス問題を測定して確認した後です。早期最適化は避けてください。

最も重要なパフォーマンスメトリクスは?

Web Vitals(LCP、FID、CLS)とユーザーが感じる応答時間です。

AIはパフォーマンス問題を自動的に修正できますか?

AIは問題を特定して提案できますが、最終的な決定と実装は開発者が行う必要があります。

パフォーマンステストはどのくらいの頻度で実行すべきですか?

CI/CDパイプラインの一部として、各デプロイ前に実行してください。

タグ

#performance#optimization#ai-tools#profiling#speed

この記事をシェア

继续阅读

関連記事