Improve packet writer performance.

This commit is contained in:
Christian
2020-12-14 21:17:22 +01:00
parent 1f78a92c4d
commit 72211ae85a
+53 -36
View File
@@ -13,11 +13,8 @@ namespace MQTTnet.Formatter
/// </summary> /// </summary>
public sealed class MqttPacketWriter : IMqttPacketWriter public sealed class MqttPacketWriter : IMqttPacketWriter
{ {
static readonly ArraySegment<byte> ZeroVariableLengthIntegerArray = new ArraySegment<byte>(new byte[1], 0, 1); public static int InitialBufferSize = 4096;
static readonly ArraySegment<byte> ZeroTwoByteIntegerArray = new ArraySegment<byte>(new byte[2], 0, 2); public static int MaxBufferSize = 4096 + 4;
public static int InitialBufferSize = 128;
public static int MaxBufferSize = 4096;
byte[] _buffer = new byte[InitialBufferSize]; byte[] _buffer = new byte[InitialBufferSize];
@@ -38,59 +35,72 @@ namespace MQTTnet.Formatter
var x = value; var x = value;
do do
{ {
x = x / 128; x /= 128;
result++; result++;
} while (x > 0); } while (x > 0);
return result; return result;
} }
public static ArraySegment<byte> EncodeVariableLengthInteger(uint value) public void WriteVariableLengthInteger(uint value)
{ {
if (value == 0) if (value == 0)
{ {
return ZeroVariableLengthIntegerArray; _buffer[_offset] = 0;
IncreasePosition(1);
return;
} }
if (value <= 127) if (value <= 127)
{ {
return new ArraySegment<byte>(new[] { (byte)value }, 0, 1); _buffer[_offset] = (byte)value;
IncreasePosition(1);
return;
} }
var buffer = new byte[4]; var size = 0;
var bufferOffset = 0;
var x = value; var x = value;
do do
{ {
var encodedByte = x % 128; var encodedByte = x % 128;
x = x / 128; x /= 128;
if (x > 0) if (x > 0)
{ {
encodedByte = encodedByte | 128; encodedByte |= 128;
} }
buffer[bufferOffset] = (byte)encodedByte; _buffer[_offset + size] = (byte)encodedByte;
bufferOffset++; size++;
} while (x > 0); } while (x > 0);
return new ArraySegment<byte>(buffer, 0, bufferOffset); IncreasePosition(size);
}
public void WriteVariableLengthInteger(uint value)
{
Write(EncodeVariableLengthInteger(value));
} }
public void WriteWithLengthPrefix(string value) public void WriteWithLengthPrefix(string value)
{ {
if (string.IsNullOrEmpty(value)) if (string.IsNullOrEmpty(value))
{ {
Write(ZeroTwoByteIntegerArray); EnsureAdditionalCapacity(2);
_buffer[_offset] = 0;
_buffer[_offset + 1] = 0;
IncreasePosition(2);
} }
else else
{ {
WriteWithLengthPrefix(Encoding.UTF8.GetBytes(value)); var bufferSize = Encoding.UTF8.GetByteCount(value);
EnsureAdditionalCapacity(bufferSize + 2);
_buffer[_offset] = (byte)(bufferSize >> 8);
_buffer[_offset + 1] = (byte)bufferSize;
Encoding.UTF8.GetBytes(value, 0, value.Length, _buffer, _offset + 2);
IncreasePosition(bufferSize + 2);
} }
} }
@@ -98,13 +108,22 @@ namespace MQTTnet.Formatter
{ {
if (value == null || value.Length == 0) if (value == null || value.Length == 0)
{ {
Write(ZeroTwoByteIntegerArray); EnsureAdditionalCapacity(2);
_buffer[_offset] = 0;
_buffer[_offset + 1] = 0;
IncreasePosition(2);
} }
else else
{ {
EnsureAdditionalCapacity(value.Length + 2); EnsureAdditionalCapacity(value.Length + 2);
Write((ushort)value.Length);
Write(value, 0, value.Length); _buffer[_offset] = (byte)(value.Length >> 8);
_buffer[_offset + 1] = (byte)value.Length;
Array.Copy(value, 0, _buffer, _offset + 2, value.Length);
IncreasePosition(value.Length + 2);
} }
} }
@@ -143,8 +162,6 @@ namespace MQTTnet.Formatter
public void Write(IMqttPacketWriter propertyWriter) public void Write(IMqttPacketWriter propertyWriter)
{ {
if (propertyWriter == null) throw new ArgumentNullException(nameof(propertyWriter));
if (propertyWriter is MqttPacketWriter writer) if (propertyWriter is MqttPacketWriter writer)
{ {
if (writer.Length == 0) if (writer.Length == 0)
@@ -156,7 +173,12 @@ namespace MQTTnet.Formatter
return; return;
} }
throw new InvalidOperationException($"{nameof(propertyWriter)} must be of type {typeof(MqttPacketWriter).Name}"); if (propertyWriter == null)
{
throw new ArgumentNullException(nameof(propertyWriter));
}
throw new InvalidOperationException($"{nameof(propertyWriter)} must be of type {nameof(MqttPacketWriter)}");
} }
public void Reset(int length) public void Reset(int length)
@@ -190,12 +212,7 @@ namespace MQTTnet.Formatter
Array.Resize(ref _buffer, MaxBufferSize); Array.Resize(ref _buffer, MaxBufferSize);
} }
void Write(ArraySegment<byte> buffer)
{
Write(buffer.Array, buffer.Offset, buffer.Count);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
void EnsureAdditionalCapacity(int additionalCapacity) void EnsureAdditionalCapacity(int additionalCapacity)
{ {