--- id: wiki-2026-0508-object-pooling title: Object Pooling category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Object Pool, Pool Pattern, Resource Pool] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [performance, memory, gamedev, design-pattern, gc] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: cpp-csharp-typescript framework: unity-unreal --- # Object Pooling ## 매 한 줄 > **"매 expensive-to-create object를 미리 만들어두고 재사용하여 alloc/free latency · GC pressure를 제거."**. 1990s 게임에서 bullet/particle GC spike 회피로 시작. 2026 현재 Unity `ObjectPool`, Unreal pooling subsystem, .NET `ArrayPool`, Netty `Recycler` 등 plat-form 표준. ## 매 핵심 ### 매 동작 원리 1. Pool이 N개 instance 미리 alloc. 2. `acquire()` → free list에서 pop. 3. 사용 후 `release()` → reset 후 free list에 return. 4. Pool 부족 시 grow (또는 block / fail). ### 매 적합한 대상 - 매 alloc cost 큼 (network connection, thread, GPU buffer). - 매 빈번한 short-lived alloc (bullet, particle, packet). - 매 size predictable. - 매 reset 가능 (no permanent dirty state). ### 매 응용 1. Game — bullets, enemies, particles, audio sources. 2. Networking — DB connection pool (HikariCP), HTTP client (Apache). 3. Rendering — command buffer pool, descriptor set pool (Vulkan). ## 💻 패턴 ### C# Unity ObjectPool (2026 standard) ```csharp using UnityEngine.Pool; public class BulletSpawner : MonoBehaviour { [SerializeField] Bullet prefab; IObjectPool pool; void Awake() { pool = new ObjectPool( createFunc: () => Instantiate(prefab), actionOnGet: b => b.gameObject.SetActive(true), actionOnRelease: b => b.gameObject.SetActive(false), actionOnDestroy: b => Destroy(b.gameObject), collectionCheck: true, defaultCapacity: 64, maxSize: 512); } public void Fire(Vector3 pos, Vector3 dir) { var b = pool.Get(); b.Init(pos, dir, onExpire: () => pool.Release(b)); } } ``` ### C++ template pool with free-list ```cpp template class ObjectPool { alignas(T) std::byte storage[N * sizeof(T)]; std::array free_list; size_t free_top = N; public: ObjectPool() { for (size_t i = 0; i < N; ++i) free_list[i] = reinterpret_cast(storage + i * sizeof(T)); } template T* acquire(Args&&... args) { if (free_top == 0) return nullptr; T* p = free_list[--free_top]; return new (p) T(std::forward(args)...); } void release(T* p) { p->~T(); free_list[free_top++] = p; } }; ``` ### TypeScript pool for Web/Node ```typescript class ObjectPool { private free: T[] = []; constructor( private factory: () => T, private reset: (t: T) => void, initial = 0, ) { for (let i = 0; i < initial; i++) this.free.push(factory()); } acquire(): T { return this.free.pop() ?? this.factory(); } release(t: T) { this.reset(t); this.free.push(t); } } // Vector2 pool example const v2Pool = new ObjectPool<{x:number,y:number}>( () => ({x:0,y:0}), v => { v.x = 0; v.y = 0; }, 256); ``` ### .NET ArrayPool — GC-friendly buffer reuse ```csharp byte[] buf = ArrayPool.Shared.Rent(4096); try { int n = await stream.ReadAsync(buf, 0, buf.Length); Process(buf.AsSpan(0, n)); } finally { ArrayPool.Shared.Return(buf, clearArray: true); } ``` ### Connection pool (HikariCP idiom in Java) ```java HikariConfig cfg = new HikariConfig(); cfg.setJdbcUrl("jdbc:postgres://..."); cfg.setMaximumPoolSize(20); cfg.setIdleTimeout(30_000); HikariDataSource ds = new HikariDataSource(cfg); try (Connection c = ds.getConnection(); // ← acquire PreparedStatement s = c.prepareStatement("...")) { s.executeQuery(); } // ← release on close() ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | GC spike from short-lived alloc | object pool | | Network/DB resource | connection pool | | Render commands | per-frame pool, reset on frame end | | Variable size buffer | ArrayPool / segregated pool | | Single-threaded game | simple stack pool | | Multi-threaded | ConcurrentBag / lock-free pool | **기본값**: 매 platform 제공 pool 사용 (Unity ObjectPool, ArrayPool, HikariCP) — 매 직접 구현 회피. ## 🔗 Graph - 부모: [[Memory_Management]] · [[Design_Patterns]] - 변형: [[Connection_Pool]] · [[Thread_Pool]] · [[Free_List]] - 응용: [[Game_Loop]] · [[Particle_Systems]] · [[Garbage_Collection]] - Adjacent: [[Old_Space]] · [[Generational_Hypothesis]] · [[Memory_Leaks]] ## 🤖 LLM 활용 **언제**: GC pressure visible (frame spike), expensive resource creation, predictable churn rate. **언제 X**: long-lived object, unique-per-instance state, alloc rate 낮음 — 매 premature opt. ## ❌ 안티패턴 - **Forget release**: 매 leak — `using`/`try-finally`/RAII. - **Use after release**: 매 use-after-free 등가 — generational handle 사용. - **Dirty state carry-over**: 매 reset 누락 — bug. - **Unbounded growth**: 매 maxSize 없음 → OOM. - **Premature pooling**: 매 GC가 충분히 빠른 경우 — measure first. ## 🧪 검증 / 중복 - Verified (Game Programming Patterns by Nystrom 2014, Unity docs 2026, .NET ArrayPool source, HikariCP). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — Object pooling pattern (4 lang impls + decision matrix) |