Skip to content

Optimize writing numeric values. #1635

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Apr 8, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Optimize writing values at absolute buffer position.
  • Loading branch information
vbabanin committed Feb 27, 2025
commit c6935642bcd86b4562828e8fb6a8810f49ee6041
11 changes: 11 additions & 0 deletions bson/src/main/org/bson/ByteBuf.java
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Note] As @stIncMale suggested, lets put Evolving annotation here.

Copy link
Member Author

@vbabanin vbabanin Apr 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stIncMale I will add it in a follow-up PR as we don't have this annotation in Bson package.

Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ public interface ByteBuf {
*/
ByteBuf putInt(int b);
Copy link
Member Author

@vbabanin vbabanin Mar 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that the interface includes the warning:

This interface is not frozen yet, and methods may be added in a minor release, so beware implementing this yourself we are justified in adding new methods to this class.

it is permissible to add new methods to this class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add @since to the javadoc for all the new methods.


/**
* Writes the given int value into this buffer at the current position,
* using the current byte order, and increments the position by 4.
*
* @param b the int value to be written
* @return this buffer
* @throws java.nio.BufferOverflowException if there are fewer than 4 bytes remaining in this buffer
* @throws java.nio.ReadOnlyBufferException if this buffer is read-only
*/
ByteBuf putInt(int index, int b);

/**
* Writes the given double value into this buffer at the current position,
* using the current byte order, and increments the position by 8.
Expand Down
6 changes: 6 additions & 0 deletions bson/src/main/org/bson/ByteBufNIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ public ByteBuf putInt(final int b) {
return this;
}

@Override
public ByteBuf putInt(final int index, final int b) {
buf.putInt(index, b);
return this;
}

@Override
public ByteBuf putDouble(final double b) {
buf.putDouble(b);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,47 @@ public void writeInt32(final int value) {
position += 4;
} else {
// fallback for edge cases
super.writeInt32(value);
write(value);
write(value >> 8);
write(value >> 16);
write(value >> 24);
}
}


@Override
public void writeInt32(final int absolutePosition, final int value) {
ensureOpen();

if (absolutePosition < 0) {
throw new IllegalArgumentException(String.format("position must be >= 0 but was %d", absolutePosition));
}

if (absolutePosition + 3 > position - 1) {
throw new IllegalArgumentException(String.format("Integer at specified position must fit within limit <= %d, " +
"but attempted to write at %d (occupies 4 bytes)", position - 1, absolutePosition + 3));
}

BufferPositionPair bufferPositionPair = getBufferPositionPair(absolutePosition);
ByteBuf byteBuffer = getByteBufferAtIndex(bufferPositionPair.bufferIndex);
int capacity = bufferPositionPair.capacity;
if (bufferPositionPair.capacity >= 4) {
byteBuffer.putInt(bufferPositionPair.position, value);
} else {
// fallback for edge cases
int valueToWrite = value;
int pos = bufferPositionPair.position;
int bufferIndex = bufferPositionPair.bufferIndex;

for (int i = 0; i < 4; i++) {
byteBuffer.put(pos++, (byte) valueToWrite);
valueToWrite = valueToWrite >> 8;
if (--capacity == 0) {
byteBuffer = getByteBufferAtIndex(++bufferIndex);
pos = 0;
capacity = byteBuffer.position();
}
}
}
}

Expand All @@ -105,20 +145,27 @@ public void writeDouble(final double value) {
position += 8;
} else {
// fallback for edge cases
super.writeDouble(value);
writeInt64(Double.doubleToRawLongBits(value));
}
}

@Override
public void writeLong(final long value) {
public void writeInt64(final long value) {
ByteBuf buf = getCurrentByteBuffer();
if (buf.remaining() >= 8) {
ensureOpen();
buf.putLong(value);
position += 8;
} else {
// fallback for edge cases
super.writeInt64(value);
write((byte) (0xFFL & (value)));
write((byte) (0xFFL & (value >> 8)));
write((byte) (0xFFL & (value >> 16)));
write((byte) (0xFFL & (value >> 24)));
write((byte) (0xFFL & (value >> 32)));
write((byte) (0xFFL & (value >> 40)));
write((byte) (0xFFL & (value >> 48)));
write((byte) (0xFFL & (value >> 56)));
}
}

Expand Down Expand Up @@ -277,7 +324,7 @@ private BufferPositionPair getBufferPositionPair(final int absolutePosition) {
bufferSize = bufferList.get(bufferIndex).position();
}

return new BufferPositionPair(bufferIndex, positionInBuffer);
return new BufferPositionPair(bufferIndex, positionInBuffer, bufferSize - positionInBuffer);
}

private void ensureOpen() {
Expand Down Expand Up @@ -328,10 +375,12 @@ public void close() {
private static final class BufferPositionPair {
private final int bufferIndex;
private int position;
private int capacity;

BufferPositionPair(final int bufferIndex, final int position) {
BufferPositionPair(final int bufferIndex, final int position, final int capacity) {
this.bufferIndex = bufferIndex;
this.position = position;
this.capacity = capacity;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ public ByteBuf putInt(final int b) {
throw new UnsupportedOperationException();
}

@Override
public ByteBuf putInt(final int index, final int b) {
throw new UnsupportedOperationException();
}

@Override
public ByteBuf putDouble(final double b) {
throw new UnsupportedOperationException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ public ByteBuf putInt(final int b) {
return this;
}

@Override
public ByteBuf putInt(final int index, final int b) {
proxied.setInt(index, b);
return this;
}

@Override
public ByteBuf putDouble(final double b) {
proxied.writeDouble(b);
Expand Down