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]

Reply via email to