Browse Source

Performance refactoring.

release/3.x.x
Christian Kratky 5 years ago
parent
commit
961a497798
6 changed files with 82 additions and 56 deletions
  1. +5
    -4
      Source/MQTTnet.AspnetCore/SpanBasedMqttPacketBodyReader.cs
  2. +3
    -3
      Source/MQTTnet/Formatter/IMqttPacketBodyReader.cs
  3. +47
    -45
      Source/MQTTnet/Formatter/MqttPacketBodyReader.cs
  4. +3
    -3
      Source/MQTTnet/Formatter/V5/MqttV500PropertiesReader.cs
  5. +1
    -1
      Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs
  6. +23
    -0
      Tests/MQTTnet.Core.Tests/Protocol_Tests.cs

+ 5
- 4
Source/MQTTnet.AspnetCore/SpanBasedMqttPacketBodyReader.cs View File

@@ -9,6 +9,7 @@ namespace MQTTnet.AspNetCore
public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader public class SpanBasedMqttPacketBodyReader : IMqttPacketBodyReader
{ {
private ReadOnlyMemory<byte> _buffer; private ReadOnlyMemory<byte> _buffer;

private int _offset; private int _offset;
public void SetBuffer(ReadOnlyMemory<byte> buffer) public void SetBuffer(ReadOnlyMemory<byte> buffer)
@@ -17,11 +18,11 @@ namespace MQTTnet.AspNetCore
_offset = 0; _offset = 0;
} }


public ulong Length => (ulong)_buffer.Length;
public int Length => _buffer.Length;


public bool EndOfStream => _buffer.Length.Equals(_offset); public bool EndOfStream => _buffer.Length.Equals(_offset);
public ulong Offset => (ulong)_offset;
public int Offset => _offset;


public byte ReadByte() public byte ReadByte()
{ {
@@ -116,9 +117,9 @@ namespace MQTTnet.AspNetCore
throw new MqttProtocolViolationException("Boolean values can be 0 or 1 only."); 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;
} }
} }
} }

+ 3
- 3
Source/MQTTnet/Formatter/IMqttPacketBodyReader.cs View File

@@ -4,9 +4,9 @@ namespace MQTTnet.Formatter
{ {
public interface IMqttPacketBodyReader public interface IMqttPacketBodyReader
{ {
ulong Length { get; }
int Length { get; }


ulong Offset { get; }
int Offset { get; }


bool EndOfStream { get; } bool EndOfStream { get; }


@@ -26,6 +26,6 @@ namespace MQTTnet.Formatter


bool ReadBoolean(); bool ReadBoolean();


void Seek(ulong position);
void Seek(int position);
} }
} }

+ 47
- 45
Source/MQTTnet/Formatter/MqttPacketBodyReader.cs View File

@@ -9,52 +9,54 @@ namespace MQTTnet.Formatter
public class MqttPacketBodyReader : IMqttPacketBodyReader public class MqttPacketBodyReader : IMqttPacketBodyReader
{ {
private readonly byte[] _buffer; private readonly byte[] _buffer;
private readonly ulong _initialOffset;
private readonly ulong _length;
private readonly int _initialOffset;
private readonly int _length;


public MqttPacketBodyReader(byte[] buffer, int offset, int length)
: this(buffer, (ulong)offset, (ulong)length)
{
}
private int _offset;


public MqttPacketBodyReader(byte[] buffer, ulong offset, ulong length)
public MqttPacketBodyReader(byte[] buffer, int offset, int length)
{ {
_buffer = buffer; _buffer = buffer;
_initialOffset = offset; _initialOffset = offset;
Offset = offset;
_offset = offset;
_length = length; _length = length;
} }


public ulong Offset { get; private set; }
public int Offset
{
get => _offset;
}


public ulong Length => _length - Offset;
public int Length => _length - _offset;


public bool EndOfStream => Offset == _length;
public bool EndOfStream => _offset == _length;


public void Seek(ulong position)
public void Seek(int position)
{ {
Offset = _initialOffset + position;
_offset = _initialOffset + position;
} }


public ArraySegment<byte> Read(uint length)
public ArraySegment<byte> Read(int length)
{ {
ValidateReceiveBuffer(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; return buffer;
} }


public byte ReadByte() public byte ReadByte()
{ {
ValidateReceiveBuffer(1); ValidateReceiveBuffer(1);
return _buffer[Offset++];

return _buffer[_offset++];
} }


public bool ReadBoolean() public bool ReadBoolean()
{ {
ValidateReceiveBuffer(1); ValidateReceiveBuffer(1);
var buffer = _buffer[Offset++];

var buffer = _buffer[_offset++];


if (buffer == 0) if (buffer == 0)
{ {
@@ -71,15 +73,15 @@ namespace MQTTnet.Formatter


public byte[] ReadRemainingData() 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() public ushort ReadTwoByteInteger()
{ {
ValidateReceiveBuffer(2); ValidateReceiveBuffer(2);


var msb = _buffer[Offset++];
var lsb = _buffer[Offset++];
var msb = _buffer[_offset++];
var lsb = _buffer[_offset++];
return (ushort)(msb << 8 | lsb); return (ushort)(msb << 8 | lsb);
} }
@@ -88,31 +90,14 @@ namespace MQTTnet.Formatter
{ {
ValidateReceiveBuffer(4); 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); 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() public uint ReadVariableLengthInteger()
{ {
var multiplier = 1; var multiplier = 1;
@@ -134,13 +119,30 @@ namespace MQTTnet.Formatter


return value; 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)] [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");
} }
} }




+ 3
- 3
Source/MQTTnet/Formatter/V5/MqttV500PropertiesReader.cs View File

@@ -9,8 +9,8 @@ namespace MQTTnet.Formatter.V5
public class MqttV500PropertiesReader public class MqttV500PropertiesReader
{ {
private readonly IMqttPacketBodyReader _body; private readonly IMqttPacketBodyReader _body;
private readonly uint _length;
private readonly ulong _targetOffset;
private readonly int _length;
private readonly int _targetOffset;


public MqttV500PropertiesReader(IMqttPacketBodyReader body) public MqttV500PropertiesReader(IMqttPacketBodyReader body)
{ {
@@ -18,7 +18,7 @@ namespace MQTTnet.Formatter.V5


if (!body.EndOfStream) if (!body.EndOfStream)
{ {
_length = body.ReadVariableLengthInteger();
_length = (int)body.ReadVariableLengthInteger();
} }


_targetOffset = body.Offset + _length; _targetOffset = body.Offset + _length;


+ 1
- 1
Tests/MQTTnet.Benchmarks/SerializerBenchmark.cs View File

@@ -57,7 +57,7 @@ namespace MQTTnet.Benchmarks


var receivedPacket = new ReceivedMqttPacket( var receivedPacket = new ReceivedMqttPacket(
header.Flags, 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); _serializer.Decode(receivedPacket);
} }


+ 23
- 0
Tests/MQTTnet.Core.Tests/Protocol_Tests.cs View File

@@ -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);
}
}
}
}

Loading…
Cancel
Save