ol.busker.buffer-pool
ByteBuffer pooling response buffers
This namespace provides a thread-safe pool that reuses ByteBuffer instances to minimize garbage collection pressure during high-throughput I/O operations. Buffers are organized into size-aligned buckets using a factor-based scheme.
How It Works
The pool groups buffers into buckets by capacity. When you request a buffer
of size N bytes, the pool rounds up to the nearest multiple of the factor
(default 2048), then looks in the corresponding bucket. If a matching buffer
is available, it’s returned immediately. Otherwise, a fresh buffer is allocated.
When you return a buffer, it’s placed back into its bucket if there’s room, subject to per-bucket and memory limits. Buffers that don’t align with bucket sizes (e.g., unusual capacities) are rejected and left for GC.
Configuration Options
-
:factor(int, default 2048) - Bucket alignment step. Buffer capacities are rounded to multiples of this value. Larger factors reduce bucket count but may waste space; smaller factors increase bucket count but improve fit. -
:min-capacity(int, default 0) - Minimum pooled capacity. Requests below this are rounded up. -
:max-capacity(int, default 65536) - Maximum pooled capacity. Buffers larger than this are allocated but never pooled on return. -
:max-bucket-size(int, default ~2x CPU cores) - Maximum buffers per bucket. Once a bucket reaches this limit, returned buffers are discarded. Use-1ornilfor unbounded buckets. -
:max-heap-memory(long, default unlimited) - Total bytes of heap buffers the pool will retain. Additional returns are rejected. -
:max-direct-memory(long, default unlimited) - Total bytes of direct buffers the pool will retain. Additional returns are rejected.
Example
(require ' [ol.busker.buffer-pool :as pool])
(def p (pool/make-bytebuffer-pool {:factor 2048
:max-capacity 65536
:max-bucket-size 16 }))
;; Borrow a 3000-byte direct buffer (rounds up to 4096).
(let [buf (pool/borrow p 3000 true )]
;; Use buf...
(pool/return p buf)) ;; returns true if pooled
(pool/dispose p)
BufferPool
Protocol for thread-safe ByteBuffer pooling.
protocol
borrow
(borrow pool size direct?)
Acquires a ByteBuffer with capacity at least size bytes.
The actual capacity may be larger due to bucket alignment. If `size` exceeds the pool's `:max-capacity`, a fresh buffer is allocated but won't be pooled on return.
Arguments: - `size` (long) - Minimum required capacity in bytes - `direct?` (boolean) - `true` for direct (off-heap) buffer, `false` for heap
Returns: - `java.nio.ByteBuffer` with `capacity >= size` and `position` at 0
return
(return pool buffer)
Returns a ByteBuffer to the pool for potential reuse.
The buffer is only pooled if: - Its capacity aligns with a bucket size (multiple of `:factor`) - The bucket isn't full (under `:max-bucket-size`) - Pool memory limits aren't exceeded (`:max-heap-memory` / `:max-direct-memory`)
Arguments: - `buffer` (ByteBuffer) - Buffer to return, or `nil` (ignored)
Returns: - `boolean` - `true` if the buffer was accepted into the pool, `false` if rejected
make-bytebuffer-pool
(make-bytebuffer-pool opts)
Create a new buffer pool instance. opts may include: :min-capacity (int) minimum pooled buffer capacity (default 0) :factor (int) capacity step/bucket factor (default 2048) :max-capacity (int) maximum pooled capacity (default 65536) :max-bucket-size (int) max buffers per bucket (-1 or nil for unbounded; default ~2x CPU) :max-heap-memory (long) pooled heap-bytes cap (0 or nil for heuristic/unlimited) :max-direct-memory (long) pooled direct-bytes cap (0 or nil for heuristic/unlimited) Returns a value that satisfies BufferPool.