fix: Stops creating blocked packets entirely (#944)
Optimizes larger servers where users are logging in and packets are being created for no reason.
This commit is contained in:
parent
5db8b1354c
commit
941452de4a
58 changed files with 5510 additions and 5537 deletions
|
|
@ -18,98 +18,97 @@ using System.Buffers;
|
|||
using System.Buffers.Binary;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Server.Network
|
||||
namespace Server.Network;
|
||||
|
||||
public ref struct PacketContainerBuilder
|
||||
{
|
||||
public ref struct PacketContainerBuilder
|
||||
public const int MinPacketLength = 5;
|
||||
|
||||
private bool _finished;
|
||||
private int _count;
|
||||
|
||||
private byte[] _arrayToReturnToPool;
|
||||
private Span<byte> _bytes;
|
||||
|
||||
public PacketContainerBuilder(Span<byte> initialBuffer)
|
||||
{
|
||||
public const int MinPacketLength = 5;
|
||||
_arrayToReturnToPool = null;
|
||||
_finished = false;
|
||||
_count = 0;
|
||||
|
||||
private bool _finished;
|
||||
private int _count;
|
||||
_bytes = initialBuffer;
|
||||
_bytes[0] = 0xF7; // Packet ID
|
||||
Length = MinPacketLength; // Length + Count
|
||||
}
|
||||
|
||||
private byte[] _arrayToReturnToPool;
|
||||
private Span<byte> _bytes;
|
||||
public int Length { get; set; }
|
||||
|
||||
public PacketContainerBuilder(Span<byte> initialBuffer)
|
||||
public int Capacity => _bytes.Length;
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public ReadOnlySpan<byte> Finalize()
|
||||
{
|
||||
if (!_finished)
|
||||
{
|
||||
_arrayToReturnToPool = null;
|
||||
_finished = false;
|
||||
_count = 0;
|
||||
|
||||
_bytes = initialBuffer;
|
||||
_bytes[0] = 0xF7; // Packet ID
|
||||
Length = MinPacketLength; // Length + Count
|
||||
BinaryPrimitives.WriteUInt16BigEndian(_bytes[1..3], (ushort)Length);
|
||||
BinaryPrimitives.WriteUInt16BigEndian(_bytes[3..5], (ushort)_count);
|
||||
}
|
||||
|
||||
public int Length { get; set; }
|
||||
return _bytes[..Length];
|
||||
}
|
||||
|
||||
public int Capacity => _bytes.Length;
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public ReadOnlySpan<byte> Finalize()
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public Span<byte> GetSpan(int bytesNeeded)
|
||||
{
|
||||
if (_finished)
|
||||
{
|
||||
if (!_finished)
|
||||
{
|
||||
BinaryPrimitives.WriteUInt16BigEndian(_bytes[1..3], (ushort)Length);
|
||||
BinaryPrimitives.WriteUInt16BigEndian(_bytes[3..5], (ushort)_count);
|
||||
}
|
||||
|
||||
return _bytes[..Length];
|
||||
throw new InvalidOperationException("Attempted to use PacketContainerBuilder after finalize");
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public Span<byte> GetSpan(int bytesNeeded)
|
||||
if (Length > _bytes.Length - bytesNeeded)
|
||||
{
|
||||
if (_finished)
|
||||
{
|
||||
throw new InvalidOperationException("Attempted to use PacketContainerBuilder after finalize");
|
||||
}
|
||||
|
||||
if (Length > _bytes.Length - bytesNeeded)
|
||||
{
|
||||
Grow(bytesNeeded);
|
||||
}
|
||||
|
||||
return _bytes[Length..];
|
||||
Grow(bytesNeeded);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public void Advance(int bytesWritten)
|
||||
{
|
||||
if (_finished)
|
||||
{
|
||||
throw new InvalidOperationException("Attempted to use PacketContainerBuilder after finalize");
|
||||
}
|
||||
return _bytes[Length..];
|
||||
}
|
||||
|
||||
_count++;
|
||||
Length += bytesWritten;
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public void Advance(int bytesWritten)
|
||||
{
|
||||
if (_finished)
|
||||
{
|
||||
throw new InvalidOperationException("Attempted to use PacketContainerBuilder after finalize");
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private void Grow(int additionalCapacityBeyondPos)
|
||||
_count++;
|
||||
Length += bytesWritten;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private void Grow(int additionalCapacityBeyondPos)
|
||||
{
|
||||
var newLength = Math.Max(Length + additionalCapacityBeyondPos, _bytes.Length * 2);
|
||||
byte[] poolArray = ArrayPool<byte>.Shared.Rent(newLength);
|
||||
|
||||
_bytes[..Length].CopyTo(poolArray);
|
||||
|
||||
byte[] toReturn = _arrayToReturnToPool;
|
||||
_bytes = _arrayToReturnToPool = poolArray;
|
||||
if (toReturn != null)
|
||||
{
|
||||
var newLength = Math.Max(Length + additionalCapacityBeyondPos, _bytes.Length * 2);
|
||||
byte[] poolArray = ArrayPool<byte>.Shared.Rent(newLength);
|
||||
|
||||
_bytes[..Length].CopyTo(poolArray);
|
||||
|
||||
byte[] toReturn = _arrayToReturnToPool;
|
||||
_bytes = _arrayToReturnToPool = poolArray;
|
||||
if (toReturn != null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(toReturn);
|
||||
}
|
||||
ArrayPool<byte>.Shared.Return(toReturn);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Dispose()
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Dispose()
|
||||
{
|
||||
byte[] toReturn = _arrayToReturnToPool;
|
||||
this = default; // for safety, to avoid using pooled array if this instance is erroneously appended to again
|
||||
if (toReturn != null)
|
||||
{
|
||||
byte[] toReturn = _arrayToReturnToPool;
|
||||
this = default; // for safety, to avoid using pooled array if this instance is erroneously appended to again
|
||||
if (toReturn != null)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(toReturn);
|
||||
}
|
||||
ArrayPool<byte>.Shared.Return(toReturn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue