Summary
Enable incremental adoption of MemorySegment VarHandle-based field accessors on the hot path by extending Agrona's buffer hierarchy with DirectBufferEx / MutableDirectBufferEx / AtomicBufferEx interfaces that carry a segment() accessor alongside the existing Unsafe-backed access.
The original goal of replacing UnsafeBuffer with SafeBuffer has evolved. Instead of a full buffer implementation swap, we extend the existing hierarchy so that every buffer in the pipeline exposes its backing MemorySegment via segment() and uses wrapAdjustment() as the index offset into the root segment — enabling zero-allocation segment access on the hot path.
Changes
Buffer type hierarchy
DirectBufferEx extends DirectBuffer — adds segment(), wrap(DirectBufferEx), wrap(MemorySegment), getBytes(MemorySegment)
MutableDirectBufferEx extends MutableDirectBuffer, DirectBufferEx — adds putBytes(DirectBufferEx), putBytes(MemorySegment)
AtomicBufferEx extends AtomicBuffer, MutableDirectBufferEx
UnsafeBufferEx extends UnsafeBuffer implements AtomicBufferEx — Unsafe-backed with segment overlay
ExpandableArrayBufferEx extends ExpandableArrayBuffer implements MutableDirectBufferEx — heap expandable
ExpandableDirectByteBufferEx extends ExpandableDirectByteBuffer implements MutableDirectBufferEx — direct expandable
Zero-allocation hot path
UnsafeBufferEx / SafeBuffer wrap methods store root backing segment instead of asSlice() per call
wrapAdjustment() used as index offset into the unsliced segment
DefaultBufferPool.buffer(slot, offset) uses wrap(DirectBufferEx, offset, length) instead of raw address wrap
Flyweight migration
- Generated
Flyweight.wrap / tryWrap / buffer() use DirectBufferEx
- Generated
Flyweight.Builder.wrap / buffer() use MutableDirectBufferEx
- Both store
segment field via buffer.segment()
Ring buffer path
MessageConsumer extends MessageHandlerEx (replaces Agrona MessageHandler)
EngineWorker uses streamsBuffer.readEx() delivering MutableDirectBufferEx
Codebase-wide type migration
- ~400+ files migrated from
DirectBuffer / MutableDirectBuffer to Ex variants
AtomicBuffer → AtomicBufferEx where assigned UnsafeBufferEx
ExpandableArrayBuffer / ExpandableDirectByteBuffer → Ex variants
References
Summary
Enable incremental adoption of
MemorySegmentVarHandle-based field accessors on the hot path by extending Agrona's buffer hierarchy withDirectBufferEx/MutableDirectBufferEx/AtomicBufferExinterfaces that carry asegment()accessor alongside the existing Unsafe-backed access.The original goal of replacing
UnsafeBufferwithSafeBufferhas evolved. Instead of a full buffer implementation swap, we extend the existing hierarchy so that every buffer in the pipeline exposes its backingMemorySegmentviasegment()and useswrapAdjustment()as the index offset into the root segment — enabling zero-allocation segment access on the hot path.Changes
Buffer type hierarchy
DirectBufferEx extends DirectBuffer— addssegment(),wrap(DirectBufferEx),wrap(MemorySegment),getBytes(MemorySegment)MutableDirectBufferEx extends MutableDirectBuffer, DirectBufferEx— addsputBytes(DirectBufferEx),putBytes(MemorySegment)AtomicBufferEx extends AtomicBuffer, MutableDirectBufferExUnsafeBufferEx extends UnsafeBuffer implements AtomicBufferEx— Unsafe-backed with segment overlayExpandableArrayBufferEx extends ExpandableArrayBuffer implements MutableDirectBufferEx— heap expandableExpandableDirectByteBufferEx extends ExpandableDirectByteBuffer implements MutableDirectBufferEx— direct expandableZero-allocation hot path
UnsafeBufferEx/SafeBufferwrap methods store root backing segment instead ofasSlice()per callwrapAdjustment()used as index offset into the unsliced segmentDefaultBufferPool.buffer(slot, offset)useswrap(DirectBufferEx, offset, length)instead of raw address wrapFlyweight migration
Flyweight.wrap/tryWrap/buffer()useDirectBufferExFlyweight.Builder.wrap/buffer()useMutableDirectBufferExsegmentfield viabuffer.segment()Ring buffer path
MessageConsumerextendsMessageHandlerEx(replaces AgronaMessageHandler)EngineWorkerusesstreamsBuffer.readEx()deliveringMutableDirectBufferExCodebase-wide type migration
DirectBuffer/MutableDirectBufferto Ex variantsAtomicBuffer→AtomicBufferExwhere assignedUnsafeBufferExExpandableArrayBuffer/ExpandableDirectByteBuffer→ Ex variantsReferences
SafeBuffer:AtomicBufferimplementation backed byMemorySegment#1719 — SafeBuffer backed by MemorySegment FFM API