オブジェクトプールパターン
生成コストの高いオブジェクトを事前に確保してプールし、再利用することでパフォーマンスを向上させるパターン
設計パターンパフォーマンス
オブジェクトプールパターンとは
オブジェクトプールパターンは、生成と破棄のコストが高いオブジェクトを事前に複数確保しておき、必要な時にプールから借り出し、使い終わったらプールに返却する設計パターンである。毎回の生成・破棄を避けることで、パフォーマンスとリソース効率を向上させる。
代表的な適用例
| 対象 | 生成コスト | プールの例 |
|---|---|---|
| DB コネクション | TCP 接続 + TLS ハンドシェイク + 認証 | pg-pool, mysql2 pool |
| HTTP クライアント | TCP 接続 + TLS ハンドシェイク | Node.js http.Agent |
| スレッド | OS スレッドの生成 | Java ThreadPoolExecutor |
| Worker | プロセス/スレッドの生成 | piscina (Node.js) |
基本的な実装
class ObjectPool<T> {
private available: T[] = [];
private inUse = new Set<T>();
constructor(
private factory: () => T,
private reset: (obj: T) => void,
private maxSize: number,
) {
for (let i = 0; i < maxSize; i++) {
this.available.push(factory());
}
}
acquire(): T | null {
const obj = this.available.pop();
if (!obj) return null; // プール枯渇
this.inUse.add(obj);
return obj;
}
release(obj: T): void {
this.inUse.delete(obj);
this.reset(obj); // 状態をリセットしてから返却
this.available.push(obj);
}
get stats() {
return { available: this.available.length, inUse: this.inUse.size };
}
}
DB コネクションプール
最も一般的な適用例。Lambda では、ハンドラーの外側でコネクションプールを初期化し、複数の呼び出しで再利用する。
プールサイズの設計
プールサイズが小さすぎると、全コネクションが使用中で待ちが発生する。大きすぎると、DB 側の接続数上限に達する。
Lambda の場合、同時実行数 × プールサイズ = DB への最大接続数になる。Lambda の同時実行数が 100 でプールサイズが 5 なら、最大 500 接続が DB に張られる。RDS Proxy を使えば、Lambda からの接続をプーリングし、DB への接続数を抑制できる。
Flyweight パターンとの違い
| パターン | 目的 | オブジェクトの状態 |
|---|---|---|
| Object Pool | 生成コストの回避 | 状態を持つ (使用後にリセット) |
| Flyweight | メモリの節約 | 不変 (共有して読み取り専用) |
実践的な知識は関連書籍でも得られる。