This is an automated email from the ASF dual-hosted git repository.
tabish pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-protonj2.git
The following commit(s) were added to refs/heads/main by this push:
new 3bae7630 PROTON-2637 Avoid excessive bounds checks for single byte
writes
3bae7630 is described below
commit 3bae7630016b0fc7e4b121f108889be6fc2c0d5c
Author: Timothy Bish <[email protected]>
AuthorDate: Thu Oct 27 18:31:55 2022 -0400
PROTON-2637 Avoid excessive bounds checks for single byte writes
For some of the types like Accepted etc the encoding is known ahead of
time and the full value can be written as an array instead of multiple
single byte writes to skip repeated bounds checks for each byte written
---
.../encoders/messaging/AcceptedTypeEncoder.java | 12 +++++++----
.../messaging/AmqpSequenceTypeEncoder.java | 14 ++++++------
.../encoders/messaging/AmqpValueTypeEncoder.java | 14 ++++++------
.../codec/encoders/messaging/DataTypeEncoder.java | 22 +++++++++++++++----
.../encoders/messaging/ReleasedTypeEncoder.java | 12 +++++++----
.../encoders/transport/DispositionTypeEncoder.java | 12 +++++++----
.../apache/qpid/protonj2/types/messaging/Data.java | 25 ++++++++++++++++++++++
7 files changed, 83 insertions(+), 28 deletions(-)
diff --git
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AcceptedTypeEncoder.java
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AcceptedTypeEncoder.java
index ea6282d0..2de17eec 100644
---
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AcceptedTypeEncoder.java
+++
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AcceptedTypeEncoder.java
@@ -29,6 +29,13 @@ import org.apache.qpid.protonj2.types.messaging.Accepted;
*/
public final class AcceptedTypeEncoder extends
AbstractDescribedListTypeEncoder<Accepted> {
+ private static final byte[] ACCEPTED_ENCODING = new byte[] {
+ EncodingCodes.DESCRIBED_TYPE_INDICATOR,
+ EncodingCodes.SMALLULONG,
+ Accepted.DESCRIPTOR_CODE.byteValue(),
+ EncodingCodes.LIST0
+ };
+
@Override
public Class<Accepted> getTypeClass() {
return Accepted.class;
@@ -51,10 +58,7 @@ public final class AcceptedTypeEncoder extends
AbstractDescribedListTypeEncoder<
@Override
public void writeType(ProtonBuffer buffer, EncoderState state, Accepted
value) {
- buffer.writeByte(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
- buffer.writeByte(EncodingCodes.SMALLULONG);
- buffer.writeByte(Accepted.DESCRIPTOR_CODE.byteValue());
- buffer.writeByte(EncodingCodes.LIST0);
+ buffer.writeBytes(ACCEPTED_ENCODING);
}
@Override
diff --git
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AmqpSequenceTypeEncoder.java
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AmqpSequenceTypeEncoder.java
index e896c0c9..2a631f31 100644
---
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AmqpSequenceTypeEncoder.java
+++
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AmqpSequenceTypeEncoder.java
@@ -33,6 +33,10 @@ import org.apache.qpid.protonj2.types.messaging.AmqpSequence;
@SuppressWarnings({ "rawtypes", "unchecked" })
public final class AmqpSequenceTypeEncoder extends
AbstractDescribedTypeEncoder<AmqpSequence> {
+ private static final byte[] SEQUENCE_PREAMBLE = new byte[] {
+ EncodingCodes.DESCRIBED_TYPE_INDICATOR, EncodingCodes.SMALLULONG,
AmqpSequence.DESCRIPTOR_CODE.byteValue()
+ };
+
@Override
public Class<AmqpSequence> getTypeClass() {
return AmqpSequence.class;
@@ -50,9 +54,7 @@ public final class AmqpSequenceTypeEncoder extends
AbstractDescribedTypeEncoder<
@Override
public void writeType(ProtonBuffer buffer, EncoderState state,
AmqpSequence value) {
- buffer.writeByte(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
- buffer.writeByte(EncodingCodes.SMALLULONG);
- buffer.writeByte(AmqpSequence.DESCRIPTOR_CODE.byteValue());
+ buffer.writeBytes(SEQUENCE_PREAMBLE);
state.getEncoder().writeList(buffer, state, value.getValue());
}
@@ -71,8 +73,8 @@ public final class AmqpSequenceTypeEncoder extends
AbstractDescribedTypeEncoder<
writeRawArray(buffer, state, values);
// Move back and write the size
- int endIndex = buffer.getWriteIndex();
- long writeSize = endIndex - startIndex - Integer.BYTES;
+ final int endIndex = buffer.getWriteIndex();
+ final long writeSize = endIndex - startIndex - Integer.BYTES;
if (writeSize > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Cannot encode given array,
encoded size to large: " + writeSize);
@@ -86,7 +88,7 @@ public final class AmqpSequenceTypeEncoder extends
AbstractDescribedTypeEncoder<
buffer.writeByte(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
state.getEncoder().writeUnsignedLong(buffer, state,
getDescriptorCode());
- List[] elements = new List[values.length];
+ final List[] elements = new List[values.length];
for (int i = 0; i < values.length; ++i) {
AmqpSequence sequence = (AmqpSequence) values[i];
diff --git
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AmqpValueTypeEncoder.java
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AmqpValueTypeEncoder.java
index 08783c55..ca23d6cf 100644
---
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AmqpValueTypeEncoder.java
+++
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/AmqpValueTypeEncoder.java
@@ -31,6 +31,10 @@ import org.apache.qpid.protonj2.types.messaging.AmqpValue;
@SuppressWarnings({ "rawtypes" })
public final class AmqpValueTypeEncoder extends
AbstractDescribedTypeEncoder<AmqpValue> {
+ private static final byte[] VALUE_PREAMBLE = new byte[] {
+ EncodingCodes.DESCRIBED_TYPE_INDICATOR, EncodingCodes.SMALLULONG,
AmqpValue.DESCRIPTOR_CODE.byteValue()
+ };
+
@Override
public Class<AmqpValue> getTypeClass() {
return AmqpValue.class;
@@ -48,9 +52,7 @@ public final class AmqpValueTypeEncoder extends
AbstractDescribedTypeEncoder<Amq
@Override
public void writeType(ProtonBuffer buffer, EncoderState state, AmqpValue
value) {
- buffer.writeByte(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
- buffer.writeByte(EncodingCodes.SMALLULONG);
- buffer.writeByte(AmqpValue.DESCRIPTOR_CODE.byteValue());
+ buffer.writeBytes(VALUE_PREAMBLE);
state.getEncoder().writeObject(buffer, state, value.getValue());
}
@@ -60,7 +62,7 @@ public final class AmqpValueTypeEncoder extends
AbstractDescribedTypeEncoder<Amq
// Write the Array Type encoding code, we don't optimize here.
buffer.writeByte(EncodingCodes.ARRAY32);
- int startIndex = buffer.getWriteIndex();
+ final int startIndex = buffer.getWriteIndex();
// Reserve space for the size and write the count of list elements.
buffer.writeInt(0);
@@ -69,8 +71,8 @@ public final class AmqpValueTypeEncoder extends
AbstractDescribedTypeEncoder<Amq
writeRawArray(buffer, state, values);
// Move back and write the size
- int endIndex = buffer.getWriteIndex();
- long writeSize = endIndex - startIndex - Integer.BYTES;
+ final int endIndex = buffer.getWriteIndex();
+ final long writeSize = endIndex - startIndex - Integer.BYTES;
if (writeSize > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Cannot encode given array,
encoded size to large: " + writeSize);
diff --git
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/DataTypeEncoder.java
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/DataTypeEncoder.java
index 8038fc6e..abbef972 100644
---
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/DataTypeEncoder.java
+++
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/DataTypeEncoder.java
@@ -29,6 +29,10 @@ import org.apache.qpid.protonj2.types.messaging.Data;
*/
public final class DataTypeEncoder extends AbstractDescribedTypeEncoder<Data> {
+ private static final byte[] DATA_PREAMBLE = new byte[] {
+ EncodingCodes.DESCRIBED_TYPE_INDICATOR, EncodingCodes.SMALLULONG,
Data.DESCRIPTOR_CODE.byteValue()
+ };
+
@Override
public Class<Data> getTypeClass() {
return Data.class;
@@ -46,11 +50,21 @@ public final class DataTypeEncoder extends
AbstractDescribedTypeEncoder<Data> {
@Override
public void writeType(ProtonBuffer buffer, EncoderState state, Data value)
{
- buffer.writeByte(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
- buffer.writeByte(EncodingCodes.SMALLULONG);
- buffer.writeByte(Data.DESCRIPTOR_CODE.byteValue());
+ buffer.writeBytes(DATA_PREAMBLE);
+
+ final int dataLength = value.getDataLength();
+
+ if (dataLength > 255) {
+ buffer.ensureWritable(dataLength + Long.BYTES);
+ buffer.writeByte(EncodingCodes.VBIN32);
+ buffer.writeInt(dataLength);
+ } else {
+ buffer.ensureWritable(dataLength + Short.BYTES);
+ buffer.writeByte(EncodingCodes.VBIN8);
+ buffer.writeByte((byte) dataLength);
+ }
- state.getEncoder().writeBinary(buffer, state, value.getBuffer());
+ value.copyTo(buffer);
}
@Override
diff --git
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/ReleasedTypeEncoder.java
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/ReleasedTypeEncoder.java
index be1258e4..3e75529d 100644
---
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/ReleasedTypeEncoder.java
+++
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/messaging/ReleasedTypeEncoder.java
@@ -29,6 +29,13 @@ import org.apache.qpid.protonj2.types.messaging.Released;
*/
public final class ReleasedTypeEncoder extends
AbstractDescribedListTypeEncoder<Released> {
+ private static final byte[] RELEASED_ENCODING = new byte[] {
+ EncodingCodes.DESCRIBED_TYPE_INDICATOR,
+ EncodingCodes.SMALLULONG,
+ Released.DESCRIPTOR_CODE.byteValue(),
+ EncodingCodes.LIST0
+ };
+
@Override
public Class<Released> getTypeClass() {
return Released.class;
@@ -51,10 +58,7 @@ public final class ReleasedTypeEncoder extends
AbstractDescribedListTypeEncoder<
@Override
public void writeType(ProtonBuffer buffer, EncoderState state, Released
value) {
- buffer.writeByte(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
- buffer.writeByte(EncodingCodes.SMALLULONG);
- buffer.writeByte(Released.DESCRIPTOR_CODE.byteValue());
- buffer.writeByte(EncodingCodes.LIST0);
+ buffer.writeBytes(RELEASED_ENCODING);
}
@Override
diff --git
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DispositionTypeEncoder.java
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DispositionTypeEncoder.java
index 73a1fb5f..8199a145 100644
---
a/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DispositionTypeEncoder.java
+++
b/protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/transport/DispositionTypeEncoder.java
@@ -31,6 +31,13 @@ import org.apache.qpid.protonj2.types.transport.Disposition;
*/
public final class DispositionTypeEncoder extends
AbstractDescribedListTypeEncoder<Disposition> {
+ private static final byte[] ACCEPTED_ENCODING = new byte[] {
+ EncodingCodes.DESCRIBED_TYPE_INDICATOR,
+ EncodingCodes.SMALLULONG,
+ Accepted.DESCRIPTOR_CODE.byteValue(),
+ EncodingCodes.LIST0
+ };
+
@Override
public UnsignedLong getDescriptorCode() {
return Disposition.DESCRIPTOR_CODE;
@@ -80,10 +87,7 @@ public final class DispositionTypeEncoder extends
AbstractDescribedListTypeEncod
case 4:
if (disposition.hasState()) {
if (disposition.getState() == Accepted.getInstance()) {
-
buffer.writeByte(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
- buffer.writeByte(EncodingCodes.SMALLULONG);
- buffer.writeByte(Accepted.DESCRIPTOR_CODE.byteValue());
- buffer.writeByte(EncodingCodes.LIST0);
+ buffer.writeBytes(ACCEPTED_ENCODING);
} else {
state.getEncoder().writeObject(buffer, state,
disposition.getState());
}
diff --git
a/protonj2/src/main/java/org/apache/qpid/protonj2/types/messaging/Data.java
b/protonj2/src/main/java/org/apache/qpid/protonj2/types/messaging/Data.java
index 1856828d..51dab672 100644
--- a/protonj2/src/main/java/org/apache/qpid/protonj2/types/messaging/Data.java
+++ b/protonj2/src/main/java/org/apache/qpid/protonj2/types/messaging/Data.java
@@ -60,6 +60,13 @@ public final class Data implements Section<byte[]> {
}
}
+ /**
+ * @return the number of actual bytes carried in this Data section.
+ */
+ public int getDataLength() {
+ return buffer == null ? 0 : buffer.getReadableBytes();
+ }
+
/**
* Returns the {@link ProtonBuffer} that contains the bytes carried in the
{@link Data} section.
* If the section carries no bytes then this method returns null. This
method allows the {@link Data}
@@ -74,6 +81,24 @@ public final class Data implements Section<byte[]> {
return buffer;
}
+ /**
+ * Copies the binary payload of this Data section info the given target
buffer.
+ *
+ * @param target
+ * The buffer where the binary payload is written to.
+ *
+ * @return this {@link Data} section instance.
+ */
+ public Data copyTo(ProtonBuffer target) {
+ if (buffer != null) {
+ buffer.markReadIndex();
+ buffer.readBytes(target, buffer.getReadableBytes());
+ buffer.resetReadIndex();
+ }
+
+ return this;
+ }
+
/**
* Returns the backing array for this Data {@link Section} copying the
contents into a new array
* instance if the backing array in the contained Binary is a subsequence
of a larger referenced
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]