Performance refactoring.

This commit is contained in:
Christian Kratky
2019-06-23 11:32:09 +02:00
parent 5a48b146b4
commit 961a497798
6 changed files with 85 additions and 59 deletions
@@ -9,6 +9,7 @@ namespace MQTTnet.AspNetCore
public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader
{
private ReadOnlyMemory<byte> _buffer;
private int _offset;
public void SetBuffer(ReadOnlyMemory<byte> buffer)
@@ -17,11 +18,11 @@ namespace MQTTnet.AspNetCore
_offset = 0;
}
public ulong Length => (ulong)_buffer.Length;
public int Length => _buffer.Length;
public bool EndOfStream => _buffer.Length.Equals(_offset);
public ulong Offset => (ulong)_offset;
public int Offset => _offset;
public byte ReadByte()
{
@@ -116,9 +117,9 @@ namespace MQTTnet.AspNetCore
throw new MqttProtocolViolationException("Boolean values can be 0 or 1 only.");
}
public void Seek(ulong position)
public void Seek(int position)
{
_offset = (int)position;
_offset = position;
}
}
}
@@ -4,9 +4,9 @@ namespace MQTTnet.Formatter
{
public interface IMqttPacketBodyReader
{
ulong Length { get; }
int Length { get; }
ulong Offset { get; }
int Offset { get; }
bool EndOfStream { get; }
@@ -26,6 +26,6 @@ namespace MQTTnet.Formatter
bool ReadBoolean();
void Seek(ulong position);
void Seek(int position);
}
}
@@ -9,52 +9,54 @@ namespace MQTTnet.Formatter
public class MqttPacketBodyReader : IMqttPacketBodyReader
{
private readonly byte[] _buffer;
private readonly ulong _initialOffset;
private readonly ulong _length;
private readonly int _initialOffset;
private readonly int _length;
private int _offset;
public MqttPacketBodyReader(byte[] buffer, int offset, int length)
: this(buffer, (ulong)offset, (ulong)length)
{
}
public MqttPacketBodyReader(byte[] buffer, ulong offset, ulong length)
{
_buffer = buffer;
_initialOffset = offset;
Offset = offset;
_offset = offset;
_length = length;
}
public ulong Offset { get; private set; }
public ulong Length => _length - Offset;
public bool EndOfStream => Offset == _length;
public void Seek(ulong position)
public int Offset
{
Offset = _initialOffset + position;
get => _offset;
}
public ArraySegment<byte> Read(uint length)
public int Length => _length - _offset;
public bool EndOfStream => _offset == _length;
public void Seek(int position)
{
_offset = _initialOffset + position;
}
public ArraySegment<byte> Read(int length)
{
ValidateReceiveBuffer(length);
var buffer = new ArraySegment<byte>(_buffer, (int)Offset, (int)length);
Offset += length;
var buffer = new ArraySegment<byte>(_buffer, (int)_offset, (int)length);
_offset += length;
return buffer;
}
public byte ReadByte()
{
ValidateReceiveBuffer(1);
return _buffer[Offset++];
return _buffer[_offset++];
}
public bool ReadBoolean()
{
ValidateReceiveBuffer(1);
var buffer = _buffer[Offset++];
var buffer = _buffer[_offset++];
if (buffer == 0)
{
@@ -71,15 +73,15 @@ namespace MQTTnet.Formatter
public byte[] ReadRemainingData()
{
return new ArraySegment<byte>(_buffer, (int)Offset, (int)(_length - Offset)).ToArray();
return new ArraySegment<byte>(_buffer, (int)_offset, (int)(_length - _offset)).ToArray();
}
public ushort ReadTwoByteInteger()
{
ValidateReceiveBuffer(2);
var msb = _buffer[Offset++];
var lsb = _buffer[Offset++];
var msb = _buffer[_offset++];
var lsb = _buffer[_offset++];
return (ushort)(msb << 8 | lsb);
}
@@ -88,31 +90,14 @@ namespace MQTTnet.Formatter
{
ValidateReceiveBuffer(4);
var byte0 = _buffer[Offset++];
var byte1 = _buffer[Offset++];
var byte2 = _buffer[Offset++];
var byte3 = _buffer[Offset++];
var byte0 = _buffer[_offset++];
var byte1 = _buffer[_offset++];
var byte2 = _buffer[_offset++];
var byte3 = _buffer[_offset++];
return (uint)(byte0 << 24 | byte1 << 16 | byte2 << 8 | byte3);
}
public byte[] ReadWithLengthPrefix()
{
return ReadSegmentWithLengthPrefix().ToArray();
}
private ArraySegment<byte> ReadSegmentWithLengthPrefix()
{
var length = ReadTwoByteInteger();
ValidateReceiveBuffer(length);
var result = new ArraySegment<byte>(_buffer, (int)Offset, length);
Offset += length;
return result;
}
public uint ReadVariableLengthInteger()
{
var multiplier = 1;
@@ -134,13 +119,30 @@ namespace MQTTnet.Formatter
return value;
}
public byte[] ReadWithLengthPrefix()
{
return ReadSegmentWithLengthPrefix().ToArray();
}
private ArraySegment<byte> ReadSegmentWithLengthPrefix()
{
var length = ReadTwoByteInteger();
ValidateReceiveBuffer(length);
var result = new ArraySegment<byte>(_buffer, (int)_offset, length);
_offset += length;
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ValidateReceiveBuffer(uint length)
private void ValidateReceiveBuffer(int length)
{
if (_length < Offset + length)
if (_length < _offset + length)
{
throw new ArgumentOutOfRangeException(nameof(_buffer), $"Expected at least {Offset + length} bytes but there are only {_length} bytes");
throw new ArgumentOutOfRangeException(nameof(_buffer), $"Expected at least {_offset + length} bytes but there are only {_length} bytes");
}
}
@@ -9,8 +9,8 @@ namespace MQTTnet.Formatter.V5
public class MqttV500PropertiesReader
{
private readonly IMqttPacketBodyReader _body;
private readonly uint _length;
private readonly ulong _targetOffset;
private readonly int _length;
private readonly int _targetOffset;
public MqttV500PropertiesReader(IMqttPacketBodyReader body)
{
@@ -18,7 +18,7 @@ namespace MQTTnet.Formatter.V5
if (!body.EndOfStream)
{
_length = body.ReadVariableLengthInteger();
_length = (int)body.ReadVariableLengthInteger();
}
_targetOffset = body.Offset + _length;
@@ -57,7 +57,7 @@ namespace MQTTnet.Benchmarks
var receivedPacket = new ReceivedMqttPacket(
header.Flags,
new MqttPacketBodyReader(_serializedPacket.Array, (ulong)(_serializedPacket.Count - header.RemainingLength), (ulong)_serializedPacket.Array.Length), 0);
new MqttPacketBodyReader(_serializedPacket.Array, _serializedPacket.Count - header.RemainingLength, _serializedPacket.Array.Length), 0);
_serializer.Decode(receivedPacket);
}
@@ -0,0 +1,23 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MQTTnet.Formatter;
namespace MQTTnet.Tests
{
[TestClass]
public class Protocol_Tests
{
[TestMethod]
public void Encode_Four_Byte_Integer()
{
for (uint i = 0; i < 268435455; i++)
{
var buffer = MqttPacketWriter.EncodeVariableLengthInteger(i);
var reader = new MqttPacketBodyReader(buffer.Array, buffer.Offset, buffer.Count);
var checkValue = reader.ReadVariableLengthInteger();
Assert.AreEqual(i, checkValue);
}
}
}
}