From 83dcc6dfcab01362464823ad14edc51c53b8ccf7 Mon Sep 17 00:00:00 2001 From: Xin Chen Date: Mon, 10 Apr 2023 15:44:42 -0700 Subject: [PATCH] Avoid byte[] allocation in string/symbol encoding --- .../Amqp/Encoding/StringEncoding.cs | 44 ++++++++++-------- .../Amqp/Encoding/SymbolEncoding.cs | 46 ++++++++++--------- 2 files changed, 50 insertions(+), 40 deletions(-) diff --git a/Microsoft.Azure.Amqp/Amqp/Encoding/StringEncoding.cs b/Microsoft.Azure.Amqp/Amqp/Encoding/StringEncoding.cs index cd7e9c72..98bda23d 100644 --- a/Microsoft.Azure.Amqp/Amqp/Encoding/StringEncoding.cs +++ b/Microsoft.Azure.Amqp/Amqp/Encoding/StringEncoding.cs @@ -31,10 +31,23 @@ public static void Encode(string value, ByteBuffer buffer) } else { - byte[] encodedData = Encoding.UTF8.GetBytes(value); - int encodeWidth = AmqpEncoding.GetEncodeWidthBySize(encodedData.Length); - AmqpBitConverter.WriteUByte(buffer, encodeWidth == FixedWidth.UByte ? FormatCode.String8Utf8 : FormatCode.String32Utf8); - StringEncoding.Encode(encodedData, encodeWidth, buffer); + int stringSize = Encoding.UTF8.GetByteCount(value); + int encodeWidth = AmqpEncoding.GetEncodeWidthBySize(stringSize); + if (encodeWidth == FixedWidth.UByte) + { + AmqpBitConverter.WriteUByte(buffer, FormatCode.String8Utf8); + AmqpBitConverter.WriteUByte(buffer, (byte)stringSize); + } + else + { + AmqpBitConverter.WriteUByte(buffer, FormatCode.String32Utf8); + AmqpBitConverter.WriteUInt(buffer, (uint)stringSize); + } + + buffer.Validate(true, stringSize); + int bytes = Encoding.UTF8.GetBytes(value, 0, value.Length, buffer.Buffer, buffer.WritePos); + Fx.Assert(bytes == stringSize, "size wrong"); + buffer.Append(stringSize); } } @@ -85,7 +98,14 @@ public override void EncodeObject(object value, bool arrayEncoding, ByteBuffer b { if (arrayEncoding) { - StringEncoding.Encode(Encoding.UTF8.GetBytes((string)value), FixedWidth.UInt, buffer); + string strValue = (string)value; + int stringSize = Encoding.UTF8.GetByteCount(strValue); + AmqpBitConverter.WriteUInt(buffer, (uint)stringSize); + + buffer.Validate(true, stringSize); + int bytes = Encoding.UTF8.GetBytes(strValue, 0, strValue.Length, buffer.Buffer, buffer.WritePos); + Fx.Assert(bytes == stringSize, "size wrong"); + buffer.Append(stringSize); } else { @@ -97,19 +117,5 @@ public override object DecodeObject(ByteBuffer buffer, FormatCode formatCode) { return StringEncoding.Decode(buffer, formatCode); } - - static void Encode(byte[] encodedData, int width, ByteBuffer buffer) - { - if (width == FixedWidth.UByte) - { - AmqpBitConverter.WriteUByte(buffer, (byte)encodedData.Length); - } - else - { - AmqpBitConverter.WriteUInt(buffer, (uint)encodedData.Length); - } - - AmqpBitConverter.WriteBytes(buffer, encodedData, 0, encodedData.Length); - } } } diff --git a/Microsoft.Azure.Amqp/Amqp/Encoding/SymbolEncoding.cs b/Microsoft.Azure.Amqp/Amqp/Encoding/SymbolEncoding.cs index 789666d0..6052b3c8 100644 --- a/Microsoft.Azure.Amqp/Amqp/Encoding/SymbolEncoding.cs +++ b/Microsoft.Azure.Amqp/Amqp/Encoding/SymbolEncoding.cs @@ -3,8 +3,6 @@ namespace Microsoft.Azure.Amqp.Encoding { - using System.Text; - sealed class SymbolEncoding : EncodingBase { public SymbolEncoding() @@ -32,10 +30,23 @@ public static void Encode(AmqpSymbol value, ByteBuffer buffer) } else { - byte[] encodedData = SystemEncoding.ASCII.GetBytes(value.Value); - int encodeWidth = AmqpEncoding.GetEncodeWidthBySize(encodedData.Length); - AmqpBitConverter.WriteUByte(buffer, encodeWidth == FixedWidth.UByte ? FormatCode.Symbol8 : FormatCode.Symbol32); - SymbolEncoding.Encode(encodedData, encodeWidth, buffer); + int stringSize = SystemEncoding.ASCII.GetByteCount(value.Value); + int encodeWidth = AmqpEncoding.GetEncodeWidthBySize(stringSize); + if (encodeWidth == FixedWidth.UByte) + { + AmqpBitConverter.WriteUByte(buffer, FormatCode.Symbol8); + AmqpBitConverter.WriteUByte(buffer, (byte)stringSize); + } + else + { + AmqpBitConverter.WriteUByte(buffer, FormatCode.Symbol32); + AmqpBitConverter.WriteUInt(buffer, (uint)stringSize); + } + + buffer.Validate(true, stringSize); + int bytes = SystemEncoding.ASCII.GetBytes(value.Value, 0, value.Value.Length, buffer.Buffer, buffer.WritePos); + Fx.Assert(bytes == stringSize, "size wrong"); + buffer.Append(stringSize); } } @@ -70,7 +81,14 @@ public override void EncodeObject(object value, bool arrayEncoding, ByteBuffer b { if (arrayEncoding) { - SymbolEncoding.Encode(SystemEncoding.ASCII.GetBytes(((AmqpSymbol)value).Value), FixedWidth.UInt, buffer); + string strValue = ((AmqpSymbol)value).Value; + int stringSize = SystemEncoding.ASCII.GetByteCount(strValue); + AmqpBitConverter.WriteUInt(buffer, (uint)stringSize); + + buffer.Validate(true, stringSize); + int bytes = SystemEncoding.ASCII.GetBytes(strValue, 0, strValue.Length, buffer.Buffer, buffer.WritePos); + Fx.Assert(bytes == stringSize, "size wrong"); + buffer.Append(stringSize); } else { @@ -82,19 +100,5 @@ public override object DecodeObject(ByteBuffer buffer, FormatCode formatCode) { return SymbolEncoding.Decode(buffer, formatCode); } - - static void Encode(byte[] encodedData, int width, ByteBuffer buffer) - { - if (width == FixedWidth.UByte) - { - AmqpBitConverter.WriteUByte(buffer, (byte)encodedData.Length); - } - else - { - AmqpBitConverter.WriteUInt(buffer, (uint)encodedData.Length); - } - - AmqpBitConverter.WriteBytes(buffer, encodedData, 0, encodedData.Length); - } } }