implement scratch space reuse

This commit is contained in:
David Renshaw 2019-05-04 10:33:55 -04:00
parent 3c60400dae
commit 755114c1a3
3 changed files with 46 additions and 0 deletions

View file

@ -52,6 +52,18 @@ public final class BuilderArena implements Arena {
this.allocator = allocator; this.allocator = allocator;
} }
public BuilderArena(Allocator allocator, ByteBuffer firstSegment) {
this.segments = new ArrayList<SegmentBuilder>();
SegmentBuilder newSegment = new SegmentBuilder(
firstSegment,
this);
newSegment.buffer.order(ByteOrder.LITTLE_ENDIAN);
newSegment.id = 0;
this.segments.add(newSegment);
this.allocator = allocator;
}
@Override @Override
public final SegmentReader tryGetSegment(int id) { public final SegmentReader tryGetSegment(int id) {
return this.segments.get(id); return this.segments.get(id);

View file

@ -40,10 +40,26 @@ public final class MessageBuilder {
allocationStrategy); allocationStrategy);
} }
/**
* Constructs a new MessageBuilder from an Allocator.
*/
public MessageBuilder(Allocator allocator) { public MessageBuilder(Allocator allocator) {
this.arena = new BuilderArena(allocator); this.arena = new BuilderArena(allocator);
} }
/**
* Constructs a new MessageBuilder from an Allocator and a given first segment buffer.
* This is useful for reusing the first segment buffer between messages, to avoid
* repeated allocations.
*
* You MUST ensure that firstSegment contains only zeroes before calling this method.
* If you are reusing firstSegment from another message, then it suffices to call
* clearFirstSegment() on that message.
*/
public MessageBuilder(Allocator allocator, java.nio.ByteBuffer firstSegment) {
this.arena = new BuilderArena(allocator, firstSegment);
}
private AnyPointer.Builder getRootInternal() { private AnyPointer.Builder getRootInternal() {
if (this.arena.segments.isEmpty()) { if (this.arena.segments.isEmpty()) {
this.arena.allocate(1); this.arena.allocate(1);
@ -78,4 +94,15 @@ public final class MessageBuilder {
public final java.nio.ByteBuffer[] getSegmentsForOutput() { public final java.nio.ByteBuffer[] getSegmentsForOutput() {
return this.arena.getSegmentsForOutput(); return this.arena.getSegmentsForOutput();
} }
/**
* Sets the first segment buffer to contain all zeros so that it can be reused in
* another message. (See the MessageBuilder(Allocator, ByteBuffer) constructor above.)
*
* After calling this method, the message will be corrupted. Therefore, you need to make
* sure to write the message (via getSegmentsForOutput()) before calling this.
*/
public final void clearFirstSegment() {
this.arena.segments.get(0).clear();
}
} }

View file

@ -72,4 +72,11 @@ public final class SegmentBuilder extends SegmentReader {
public final void put(int index, long value) { public final void put(int index, long value) {
buffer.putLong(index * Constants.BYTES_PER_WORD, value); buffer.putLong(index * Constants.BYTES_PER_WORD, value);
} }
public final void clear() {
for (int ii = 0; ii < this.pos; ++ii) {
this.put(ii, 0);
}
this.pos = 0;
}
} }