performance-optimization について
Node.jsバックエンドの性能改善を学ぶ開発者向けスキルです。キャッシュ、クラスタリング、プロファイリング、データベースやレスポンスの最適化、監視をコード例と本番向けチェックリストで扱います。
主な機能
- 01Redisとインメモリキャッシュ
- 02クラスタリングによるCPU活用
- 03CPUとメモリのプロファイリング
- 04データベースクエリと接続プールの最適化
- 05レスポンスの圧縮とページネーション
- 06性能監視と負荷テスト
活用シーン
- 01バックエンドの応答遅延の診断
- 02Node.jsサービスの本番準備
- 03データベースクエリのボトルネック解消
- 04トラフィック下での挙動評価
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ pluginagentmarketplace/ custom-plugin-nodejs --skill performance-optimizationインストール後、Claude Code で/performance-optimizationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/config.yamlreferences/GUIDE.mdscripts/helper.py詳細
パフォーマンス最適化スキル
高速でスケーラブル、効率的なバックエンドアプリケーションを実現するために、Node.js のパフォーマンス最適化を習得しましょう。
クイックスタート
次の 4 つの領域を最適化します。
- キャッシュ - Redis/インメモリキャッシュ
- クラスタリング - すべての CPU コアを使用
- プロファイリング - ボトルネックを特定
- モニタリング - パフォーマンスを追跡
基本概念
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 デプロイ(本番環境へのデプロイ)
リソース
コメント
Markdown 対応