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
{
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;
}
}
}

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

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

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

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

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;
_initialOffset = offset;
Offset = offset;
_offset = offset;
_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);

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



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

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


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

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


+ 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