← Concepts

阅读中文版本

Object Pooling

Object pooling reuses preallocated instances instead of allocating per use, trading initialization cost for pool management — and in managed runtimes often fighting the collector it meant to help.

performance

Definition

An object pool maintains a set of initialized instances, lending them out and taking them back instead of constructing and discarding. Pools win when construction is expensive, when allocation triggers GC pressure, or when resources are scarce — connections, buffers, threads. In modern generational runtimes, pooling small short-lived objects can be slower than allocating them.

Context and scope

Applied for connection pools, buffer pools, and heavyweight framework objects. Tuned with max size, idle eviction, health checks, and borrow timeouts.

Common misconceptions

  • Pooling always beats allocation in GC languages — young-generation allocation is pointer-bump cheap; pooling can promote garbage and enlarge the old generation
  • A pool prevents leaks — pools cause leaks when borrowers never return; discipline and timeouts are still required
  • Pool size should be as large as possible — oversized pools hold memory and resources idle and hurt downstream capacity

Anti-patterns

  • Pooling trivially cheap objects and paying synchronization plus stale-state bugs for negative gains
  • Returning objects without resetting state and leaking data between borrowers
  • Sharing one pool for objects with different initialization costs and starving the cheap ones behind the expensive

Related concepts

Authoritative source

https://en.wikipedia.org/wiki/Object_pool_pattern

What it is

Construction and teardown have costs: object initialization, resource acquisition, collector bookkeeping. A pool amortizes both by cycling instances through borrowers.

How it works

The pool exposes acquire and release with semantics for max size, borrow timeout, and validation on acquire or on return. Reset happens on release or acquisition — the safer point — clearing references and state. Idle eviction shrinks the pool under low load; health validation drops broken instances.

When to pool

Genuinely expensive resources: database connections, native buffers, threads, large byte arrays. Measure first in managed runtimes: escape-analysis and TLAB allocation make many small objects nearly free to allocate and collect.

Pitfalls

Stale state between borrowers is the classic security bug — reset lists must be explicit and tested. Pooling arrays that grow means borrowers hold max-size memory always. In generational collectors, pooled objects live long, inflating the old generation and pause work — the pool becomes GC pressure it claimed to remove.