mcpField
P
performance-optimization

performance-optimization

github.com/pluginagentmarketplace開発264 回インストール43 週間前に更新
リポジトリ

performance-optimization について

Node.jsバックエンドの性能改善を学ぶ開発者向けスキルです。キャッシュ、クラスタリング、プロファイリング、データベースやレスポンスの最適化、監視をコード例と本番向けチェックリストで扱います。

主な機能

  1. 01Redisとインメモリキャッシュ
  2. 02クラスタリングによるCPU活用
  3. 03CPUとメモリのプロファイリング
  4. 04データベースクエリと接続プールの最適化
  5. 05レスポンスの圧縮とページネーション
  6. 06性能監視と負荷テスト

活用シーン

  1. 01バックエンドの応答遅延の診断
  2. 02Node.jsサービスの本番準備
  3. 03データベースクエリのボトルネック解消
  4. 04トラフィック下での挙動評価

インストール

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

$npx skills add https://github.com/pluginagentmarketplace/custom-plugin-nodejs --skill performance-optimization

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/
config.yaml
references/
GUIDE.md
scripts/
helper.py

詳細

パフォーマンス最適化スキル

高速でスケーラブル、効率的なバックエンドアプリケーションを実現するために、Node.js のパフォーマンス最適化を習得しましょう。

クイックスタート

次の 4 つの領域を最適化します。

  1. キャッシュ - Redis/インメモリキャッシュ
  2. クラスタリング - すべての CPU コアを使用
  3. プロファイリング - ボトルネックを特定
  4. モニタリング - パフォーマンスを追跡

基本概念

Redis によるキャッシュ
const redis = require('redis');
const client = redis.createClient({ url: process.env.REDIS_URL });

// Cache middleware
async function cacheMiddleware(req, res, next) {
  const key = `cache:${req.originalUrl}`;

  const cached = await client.get(key);
  if (cached) {
    return res.json(JSON.parse(cached));
  }

  // Override res.json to cache response
  const originalJson = res.json.bind(res);
  res.json = (data) => {
    client.setEx(key, 3600, JSON.stringify(data)); // 1 hour
    originalJson(data);
  };

  next();
}

// Usage
app.get('/api/users', cacheMiddleware, getUsers);
クラスタリング(すべての CPU コアを使用)
const cluster = require('cluster');
const os = require('os');

if (cluster.isMaster) {
  const numCPUs = os.cpus().length;

  console.log(`Master ${process.pid} starting ${numCPUs} workers`);

  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker) => {
    console.log(`Worker ${worker.process.pid} died, restarting...`);
    cluster.fork();
  });
} else {
  // Worker process - start Express server
  const app = require('./app');
  app.listen(3000, () => {
    console.log(`Worker ${process.pid} started`);
  });
}

学習パス

初級(2~3 週間)
  • ✅ 基本的なキャッシュを実装する
  • ✅ 圧縮ミドルウェアを使用する
  • ✅ データベースクエリを最適化する
  • ✅ 本番モードを有効にする
中級(4~5 週間)
  • ✅ Redis キャッシュを設定する
  • ✅ クラスタリングを実装する
  • ✅ データベースのインデックスを設定する
  • ✅ レスポンスのページネーションを実装する
上級(6~8 週間)
  • ✅ CPU/メモリのプロファイリング
  • ✅ 負荷分散
  • ✅ CDN の統合
  • ✅ パフォーマンスモニタリング

データベースの最適化

コネクションプーリング
// PostgreSQL pool
const { Pool } = require('pg');

const pool = new Pool({
  max: 20,  // Max connections
  min: 5,   // Min connections
  idleTimeoutMillis: 30000
});

// MongoDB with Mongoose
mongoose.connect(uri, {
  maxPoolSize: 10,
  minPoolSize: 5
});
クエリの最適化
// ❌ Bad: N+1 query problem
const users = await User.find();
for (const user of users) {
  user.posts = await Post.find({ userId: user.id }); // N queries
}

// ✅ Good: Single query with join
const users = await User.find().populate('posts'); // 1 query

// Add indexes
userSchema.index({ email: 1 }, { unique: true });
userSchema.index({ createdAt: -1 });

// Use lean() for read-only queries (faster)
const users = await User.find().lean(); // Returns plain objects
ページネーション
async function getUsers(req, res) {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  const skip = (page - 1) * limit;

  const [users, total] = await Promise.all([
    User.find().limit(limit).skip(skip),
    User.countDocuments()
  ]);

  res.json({
    data: users,
    pagination: {
      page,
      limit,
      total,
      pages: Math.ceil(total / limit)
    }
  });
}

レスポンスの最適化

圧縮
const compression = require('compression');

app.use(compression({
  level: 6,
  threshold: 1024  // Only compress > 1KB
}));
レスポンスのキャッシュヘッダー
app.get('/api/static-data', (req, res) => {
  res.set('Cache-Control', 'public, max-age=3600'); // Cache 1 hour
  res.json(data);
});

// For frequently changing data
res.set('Cache-Control', 'public, max-age=60'); // Cache 1 minute

非同期処理の最適化

並列実行
// ❌ Sequential (300ms)
const users = await getUsers();    // 100ms
const posts = await getPosts();    // 100ms
const comments = await getComments(); // 100ms

// ✅ Parallel (100ms)
const [users, posts, comments] = await Promise.all([
  getUsers(),
  getPosts(),
  getComments()
]);
大容量ファイルのストリーミング
const fs = require('fs');

// ❌ Bad: Load entire file into memory
app.get('/large-file', async (req, res) => {
  const data = await fs.promises.readFile('large.txt');
  res.send(data);
});

// ✅ Good: Stream file
app.get('/large-file', (req, res) => {
  const stream = fs.createReadStream('large.txt');
  stream.pipe(res);
});

CPU プロファイリング

組み込みプロファイラー
# Start with profiler
node --prof app.js

# Generate readable output
node --prof-process isolate-0x*.log > profile.txt
パフォーマンス測定
const { performance } = require('perf_hooks');

const start = performance.now();
await heavyOperation();
const end = performance.now();
console.log(`Operation took ${end - start}ms`);

メモリの最適化

メモリリークを回避する
// ❌ Bad: Memory leak
const cache = {};
app.get('/data/:id', (req, res) => {
  cache[req.params.id] = data; // Never cleaned up
  res.json(data);
});

// ✅ Good: Use LRU cache with limits
const LRU = require('lru-cache');
const cache = new LRU({
  max: 500,  // Max 500 items
  maxAge: 1000 * 60 * 60  // TTL: 1 hour
});
メモリを監視する
const used = process.memoryUsage();
console.log({
  rss: `${Math.round(used.rss / 1024 / 1024)}MB`,
  heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`,
  heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`
});

モニタリングと APM

Winston によるロギング
const winston = require('winston');

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' })
  ]
});

// Request logging
app.use((req, res, next) => {
  const start = Date.now();

  res.on('finish', () => {
    logger.info('HTTP Request', {
      method: req.method,
      url: req.url,
      status: res.statusCode,
      duration: Date.now() - start
    });
  });

  next();
});
APM ツール
  • New Relic - フルスタックモニタリング
  • Datadog - インフラストラクチャと APM
  • Dynatrace - AI を活用したモニタリング
  • PM2 Plus - Node.js に特化したモニタリング

負荷テスト

Artillery
# load-test.yml
config:
  target: 'http://localhost:3000'
  phases:
    - duration: 60
      arrivalRate: 10

scenarios:
  - name: "Get users"
    flow:
      - get:
          url: "/api/users"
artillery run load-test.yml

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

  • ✅ Node.js の本番モードを有効にする(NODE_ENV=production)
  • ✅ クラスタリングを使用する(PM2 または cluster モジュール)
  • ✅ キャッシュを実装する(Redis)
  • ✅ データベースのコネクションプーリングを設定する
  • ✅ データベースのインデックスを追加する
  • ✅ レスポンスを圧縮する(gzip)
  • ✅ 静的アセットに CDN を使用する
  • ✅ 画像を最適化する
  • ✅ 大規模なデータセットにページネーションを適用する
  • ✅ 大容量ファイルをストリーミングする
  • ✅ APM ツールでモニタリングする

本番環境向けの最適化

// production.js
if (process.env.NODE_ENV === 'production') {
  // Trust proxy (for load balancer)
  app.set('trust proxy', 1);

  // Disable x-powered-by header
  app.disable('x-powered-by');

  // Enable compression
  app.use(compression());

  // Use production logger
  app.use(productionLogger());
}

使用する場面

次の場合にパフォーマンスを最適化します。

  • アプリケーションの動作が遅い、または応答しない
  • 大量のトラフィックに対応する必要がある
  • データベースクエリがボトルネックになっている
  • メモリ使用量が多い
  • 水平スケーリングを行う
  • 本番環境へのデプロイに備える

関連スキル

  • Express REST API(API パフォーマンスの最適化)
  • 非同期プログラミング(非同期処理の最適化)
  • データベース統合(クエリの最適化)
  • Docker デプロイ(本番環境へのデプロイ)

リソース

コメント