Class RecyclerBytesStreamOutput

All Implemented Interfaces:
Closeable, Flushable, AutoCloseable, Releasable

public class RecyclerBytesStreamOutput extends BytesStream implements Releasable
A @link StreamOutput that uses a Recycler<org.apache.lucene.util.BytesRef> to acquire pages of bytes, which avoids frequent reallocation & copying of the internal data. When close() is called, the bytes will be released.

Best only used for outputs which are either short-lived or large, because the resulting ReleasableBytesReference retains whole pages and this overhead may be significant on small and long-lived objects. A RecyclerBytesStreamOutput obtains pages (16kiB slices of a larger byte[]) from a Recycler<BytesRef> rather than using the BigArrays abstraction that BytesStreamOutput and ReleasableBytesStreamOutput both use. This means it can access the underlying byte[] directly and therefore avoids the intermediate buffer and the copy for almost all writes (the exception being occasional writes that get too close to the end of a page).

It does not attempt to grow its collector slowly in the same way that BigArrays.resize(org.elasticsearch.common.util.ByteArray, long) does. Instead, it always obtains from the recycler a whole new 16kiB page when the need arises. This works best when the serialized data has a short lifespan (e.g. it is an outbound network message) so the overhead has limited impact and the savings on allocations and copying (due to the absence of resize operations) are significant.

The resulting ReleasableBytesReference is a view over the underlying byte[] pages and involves no significant extra allocation to obtain. It is oversized: The worst case for overhead is when the data is a single byte, since this takes up a whole 16kiB page almost all of which is overhead. Nonetheless, if recycled pages are available then it may still be preferable to use them via a RecyclerBytesStreamOutput. If the result is large then the overhead is less important, and if the result will only be used for a short time, for instance soon being written to the network or to disk, then the imminent recycling of these pages may mean it is ok to keep it as-is. For results which are both small and long-lived it may be better to copy them into a freshly-allocated byte[].

Any memory allocated in this way is tracked by the org.elasticsearch.common.breaker subsystem if and only if the caller passes in a non-null CircuitBreaker at creation time. If the provided CircuitBreaker is null then the allocations performed here are untracked by circuit-breakers, even if the Recycler<BytesRef> was obtained from BigArrays.bytesRefRecycler().