Skip to content

Commit

Permalink
Network perf improvements (#4205)
Browse files Browse the repository at this point in the history
* initial

* More networking improvements
  • Loading branch information
Mag-nus authored Jul 23, 2024
1 parent 8e37308 commit e2e88b7
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 84 deletions.
5 changes: 3 additions & 2 deletions Source/ACE.Common/Cryptography/Hash32.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using System;
using System.Buffers.Binary;

namespace ACE.Common.Cryptography
{
public static class Hash32
{
public static uint Calculate(byte[] data, int length)
public static uint Calculate(Span<byte> data, int length)
{
uint checksum = (uint)length << 16;

for (int i = 0; i < length && i + 4 <= length; i += 4)
checksum += BitConverter.ToUInt32(data, i);
checksum += BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(i));

int shift = 3;
int j = (length / 4) * 4;
Expand Down
21 changes: 9 additions & 12 deletions Source/ACE.Server/Network/ClientPacketFragment.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Buffers;
using System;
using System.IO;

using ACE.Common.Cryptography;
Expand All @@ -10,30 +10,27 @@ public class ClientPacketFragment : PacketFragment
public bool Unpack(BinaryReader payload)
{
Header.Unpack(payload);

if (Header.Size - PacketFragmentHeader.HeaderSize < 0)
return false;

if (Header.Size > 464)
return false;

Data = payload.ReadBytes(Header.Size - PacketFragmentHeader.HeaderSize);

return true;
}

public uint CalculateHash32()
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(PacketFragmentHeader.HeaderSize);
Span<byte> buffer = stackalloc byte[PacketFragmentHeader.HeaderSize];

try
{
Header.Pack(buffer);
Header.Pack(buffer);

uint fragmentChecksum = Hash32.Calculate(buffer, buffer.Length) + Hash32.Calculate(Data, Data.Length);
uint fragmentChecksum = Hash32.Calculate(buffer, buffer.Length) + Hash32.Calculate(Data, Data.Length);

return fragmentChecksum;
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
return fragmentChecksum;
}
}
}
1 change: 0 additions & 1 deletion Source/ACE.Server/Network/NetworkSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
using ACE.Server.Network.Packets;

using log4net;
using log4net.Util;

namespace ACE.Server.Network
{
Expand Down
4 changes: 2 additions & 2 deletions Source/ACE.Server/Network/PacketFragment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ namespace ACE.Server.Network
{
public abstract class PacketFragment
{
public static int MaxFragementSize { get; } = 464; // Packet.MaxPacketSize - PacketHeader.HeaderSize
public static int MaxFragmentDataSize { get; } = 448; // Packet.MaxPacketSize - PacketHeader.HeaderSize - PacketFragmentHeader.HeaderSize
public const int MaxFragementSize = 464; // Packet.MaxPacketSize - PacketHeader.HeaderSize
public const int MaxFragmentDataSize = 448; // Packet.MaxPacketSize - PacketHeader.HeaderSize - PacketFragmentHeader.HeaderSize

public PacketFragmentHeader Header { get; } = new PacketFragmentHeader();
public byte[] Data { get; protected set; }
Expand Down
35 changes: 12 additions & 23 deletions Source/ACE.Server/Network/PacketFragmentHeader.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;
using System.Buffers.Binary;
using System.IO;

using ACE.Common.Cryptography;
Expand All @@ -6,7 +8,7 @@ namespace ACE.Server.Network
{
public class PacketFragmentHeader
{
public static int HeaderSize { get; } = 16;
public const int HeaderSize = 16;

public uint Sequence { get; set; }
public uint Id { get; set; }
Expand Down Expand Up @@ -35,34 +37,21 @@ public void Unpack(byte[] buffer, int offset = 0)
Queue = (ushort)(buffer[offset++] | (buffer[offset++] << 8));
}

public void Pack(byte[] buffer, int offset = 0)
public void Pack(Span<byte> buffer, int offset = 0)
{
Pack(buffer, ref offset);
}

public void Pack(byte[] buffer, ref int offset)
public void Pack(Span<byte> buffer, ref int offset)
{
buffer[offset++] = (byte)Sequence;
buffer[offset++] = (byte)(Sequence >> 8);
buffer[offset++] = (byte)(Sequence >> 16);
buffer[offset++] = (byte)(Sequence >> 24);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), Sequence);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 4), Id);
BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(offset + 8), Count);
BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(offset + 10), Size);
BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(offset + 12), Index);
BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(offset + 14), Queue);

buffer[offset++] = (byte)Id;
buffer[offset++] = (byte)(Id >> 8);
buffer[offset++] = (byte)(Id >> 16);
buffer[offset++] = (byte)(Id >> 24);

buffer[offset++] = (byte)Count;
buffer[offset++] = (byte)(Count >> 8);

buffer[offset++] = (byte)Size;
buffer[offset++] = (byte)(Size >> 8);

buffer[offset++] = (byte)Index;
buffer[offset++] = (byte)(Index >> 8);

buffer[offset++] = (byte)Queue;
buffer[offset++] = (byte)(Queue >> 8);
offset += 16;
}

/// <summary>
Expand Down
60 changes: 17 additions & 43 deletions Source/ACE.Server/Network/PacketHeader.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.IO;

using ACE.Common.Cryptography;
Expand All @@ -8,7 +8,7 @@ namespace ACE.Server.Network
{
public class PacketHeader
{
public static int HeaderSize { get; } = 20;
public const int HeaderSize = 20;

public uint Sequence { get; set; }
public PacketHeaderFlags Flags { get; set; }
Expand Down Expand Up @@ -41,56 +41,30 @@ public void Unpack(byte[] buffer, int offset = 0)
Iteration = (ushort)(buffer[offset++] | (buffer[offset++] << 8));
}

public void Pack(byte[] buffer, int offset = 0)
public void Pack(Span<byte> buffer, int offset = 0)
{
buffer[offset++] = (byte)Sequence;
buffer[offset++] = (byte)(Sequence >> 8);
buffer[offset++] = (byte)(Sequence >> 16);
buffer[offset++] = (byte)(Sequence >> 24);

buffer[offset++] = (byte)Flags;
buffer[offset++] = (byte)((int)Flags >> 8);
buffer[offset++] = (byte)((int)Flags >> 16);
buffer[offset++] = (byte)((int)Flags >> 24);

buffer[offset++] = (byte)Checksum;
buffer[offset++] = (byte)(Checksum >> 8);
buffer[offset++] = (byte)(Checksum >> 16);
buffer[offset++] = (byte)(Checksum >> 24);

buffer[offset++] = (byte)Id;
buffer[offset++] = (byte)(Id >> 8);

buffer[offset++] = (byte)Time;
buffer[offset++] = (byte)(Time >> 8);

buffer[offset++] = (byte)Size;
buffer[offset++] = (byte)(Size >> 8);

buffer[offset++] = (byte)Iteration;
buffer[offset++] = (byte)(Iteration >> 8);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset), Sequence);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 4), (uint)Flags);
BinaryPrimitives.WriteUInt32LittleEndian(buffer.Slice(offset + 8), Checksum);
BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(offset + 12), Id);
BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(offset + 14), Time);
BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(offset + 16), Size);
BinaryPrimitives.WriteUInt16LittleEndian(buffer.Slice(offset + 18), Iteration);
}

public uint CalculateHash32()
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(HeaderSize);
Span<byte> buffer = stackalloc byte[HeaderSize];

try
{
uint original = Checksum;
Checksum = 0xBADD70DD;
uint original = Checksum;
Checksum = 0xBADD70DD;

Pack(buffer);
Pack(buffer);

var checksum = Hash32.Calculate(buffer, HeaderSize);
Checksum = original;
var checksum = Hash32.Calculate(buffer, HeaderSize);
Checksum = original;

return checksum;
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
return checksum;
}

public bool HasFlag(PacketHeaderFlags flags) { return (flags & Flags) != 0; }
Expand Down
2 changes: 1 addition & 1 deletion Source/ACE.Server/Network/ServerPacket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace ACE.Server.Network
public class ServerPacket : Packet
{
// TODO: I don't know why this value is 464. The reasoning and math needs to be documented here.
public static int MaxPacketSize { get; } = 464;
public const int MaxPacketSize = 464;

/// <summary>
/// Make sure you call InitializeDataWriter() before you use this
Expand Down

0 comments on commit e2e88b7

Please sign in to comment.