using System; using System.Buffers.Binary; using System.IO; using BenchmarkDotNet.Attributes; namespace Content.Benchmarks { [SimpleJob] public class NetSerializerIntBenchmark { private MemoryStream _writeStream; private MemoryStream _readStream; private ushort _x16 = 5; private uint _x32 = 5; private ulong _x64 = 5; private ushort _read16; private uint _read32; private ulong _read64; [GlobalSetup] public void Setup() { _writeStream = new MemoryStream(64); _readStream = new MemoryStream(); _readStream.Write(new byte[]{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}); } [Benchmark] public void BenchWrite16Span() { _writeStream.Position = 0; WriteUInt16Span(_writeStream, _x16); } [Benchmark] public void BenchWrite32Span() { _writeStream.Position = 0; WriteUInt32Span(_writeStream, _x32); } [Benchmark] public void BenchWrite64Span() { _writeStream.Position = 0; WriteUInt64Span(_writeStream, _x64); } [Benchmark] public void BenchRead16Span() { _readStream.Position = 0; _read16 = ReadUInt16Span(_readStream); } [Benchmark] public void BenchRead32Span() { _readStream.Position = 0; _read32 = ReadUInt32Span(_readStream); } [Benchmark] public void BenchRead64Span() { _readStream.Position = 0; _read64 = ReadUInt64Span(_readStream); } [Benchmark] public void BenchWrite16Byte() { _writeStream.Position = 0; WriteUInt16Byte(_writeStream, _x16); } [Benchmark] public void BenchWrite32Byte() { _writeStream.Position = 0; WriteUInt32Byte(_writeStream, _x32); } [Benchmark] public void BenchWrite64Byte() { _writeStream.Position = 0; WriteUInt64Byte(_writeStream, _x64); } [Benchmark] public void BenchRead16Byte() { _readStream.Position = 0; _read16 = ReadUInt16Byte(_readStream); } [Benchmark] public void BenchRead32Byte() { _readStream.Position = 0; _read32 = ReadUInt32Byte(_readStream); } [Benchmark] public void BenchRead64Byte() { _readStream.Position = 0; _read64 = ReadUInt64Byte(_readStream); } private static void WriteUInt16Byte(Stream stream, ushort value) { stream.WriteByte((byte) value); stream.WriteByte((byte) (value >> 8)); } private static void WriteUInt32Byte(Stream stream, uint value) { stream.WriteByte((byte) value); stream.WriteByte((byte) (value >> 8)); stream.WriteByte((byte) (value >> 16)); stream.WriteByte((byte) (value >> 24)); } private static void WriteUInt64Byte(Stream stream, ulong value) { stream.WriteByte((byte) value); stream.WriteByte((byte) (value >> 8)); stream.WriteByte((byte) (value >> 16)); stream.WriteByte((byte) (value >> 24)); stream.WriteByte((byte) (value >> 32)); stream.WriteByte((byte) (value >> 40)); stream.WriteByte((byte) (value >> 48)); stream.WriteByte((byte) (value >> 56)); } private static ushort ReadUInt16Byte(Stream stream) { ushort a = 0; for (var i = 0; i < 16; i += 8) { var val = stream.ReadByte(); if (val == -1) throw new EndOfStreamException(); a |= (ushort) (val << i); } return a; } private static uint ReadUInt32Byte(Stream stream) { uint a = 0; for (var i = 0; i < 32; i += 8) { var val = stream.ReadByte(); if (val == -1) throw new EndOfStreamException(); a |= (uint) (val << i); } return a; } private static ulong ReadUInt64Byte(Stream stream) { ulong a = 0; for (var i = 0; i < 64; i += 8) { var val = stream.ReadByte(); if (val == -1) throw new EndOfStreamException(); a |= (ulong) (val << i); } return a; } private static void WriteUInt16Span(Stream stream, ushort value) { Span buf = stackalloc byte[2]; BinaryPrimitives.WriteUInt16LittleEndian(buf, value); stream.Write(buf); } private static void WriteUInt32Span(Stream stream, uint value) { Span buf = stackalloc byte[4]; BinaryPrimitives.WriteUInt32LittleEndian(buf, value); stream.Write(buf); } private static void WriteUInt64Span(Stream stream, ulong value) { Span buf = stackalloc byte[8]; BinaryPrimitives.WriteUInt64LittleEndian(buf, value); stream.Write(buf); } private static ushort ReadUInt16Span(Stream stream) { Span buf = stackalloc byte[2]; var wSpan = buf; while (true) { var read = stream.Read(wSpan); if (read == 0) throw new EndOfStreamException(); if (read == wSpan.Length) break; wSpan = wSpan[read..]; } return BinaryPrimitives.ReadUInt16LittleEndian(buf); } private static uint ReadUInt32Span(Stream stream) { Span buf = stackalloc byte[4]; var wSpan = buf; while (true) { var read = stream.Read(wSpan); if (read == 0) throw new EndOfStreamException(); if (read == wSpan.Length) break; wSpan = wSpan[read..]; } return BinaryPrimitives.ReadUInt32LittleEndian(buf); } private static ulong ReadUInt64Span(Stream stream) { Span buf = stackalloc byte[8]; var wSpan = buf; while (true) { var read = stream.Read(wSpan); if (read == 0) throw new EndOfStreamException(); if (read == wSpan.Length) break; wSpan = wSpan[read..]; } return BinaryPrimitives.ReadUInt64LittleEndian(buf); } } }