NetworkReader/Writer: always write integers as VarInt

This commit is contained in:
mischa 2024-07-21 15:57:03 +02:00
parent 363b6636e0
commit 3b8fb8d2a4
3 changed files with 57 additions and 19 deletions

View File

@ -33,17 +33,34 @@ public static class NetworkReaderExtensions
public static ushort ReadUShort(this NetworkReader reader) => reader.ReadBlittable<ushort>(); public static ushort ReadUShort(this NetworkReader reader) => reader.ReadBlittable<ushort>();
public static ushort? ReadUShortNullable(this NetworkReader reader) => reader.ReadBlittableNullable<ushort>(); public static ushort? ReadUShortNullable(this NetworkReader reader) => reader.ReadBlittableNullable<ushort>();
public static int ReadInt(this NetworkReader reader) => reader.ReadBlittable<int>(); // integer bandwidth optimization: write all ints as varint!
public static int? ReadIntNullable(this NetworkReader reader) => reader.ReadBlittableNullable<int>(); // reduces bandwidth for almost all integers.
// increaes bandwidth for very few large integers like hashes.
// => very much worth it for Mirror (see Benchmarks)
// => very much worth it for users (they won't have to compress manually)
public static int ReadInt(this NetworkReader reader) => (int)Compression.DecompressVarInt(reader);
public static int? ReadIntNullable(this NetworkReader reader)
{
return reader.ReadBool() ? (int)Compression.DecompressVarInt(reader) : default;
}
public static uint ReadUInt(this NetworkReader reader) => reader.ReadBlittable<uint>(); public static uint ReadUInt(this NetworkReader reader) => (uint)Compression.DecompressVarUInt(reader);
public static uint? ReadUIntNullable(this NetworkReader reader) => reader.ReadBlittableNullable<uint>(); public static uint? ReadUIntNullable(this NetworkReader reader)
{
return reader.ReadBool() ? (uint)Compression.DecompressVarUInt(reader) : default;
}
public static long ReadLong(this NetworkReader reader) => reader.ReadBlittable<long>(); public static long ReadLong(this NetworkReader reader) => Compression.DecompressVarInt(reader);
public static long? ReadLongNullable(this NetworkReader reader) => reader.ReadBlittableNullable<long>(); public static long? ReadLongNullable(this NetworkReader reader)
{
return reader.ReadBool() ? Compression.DecompressVarInt(reader) : default;
}
public static ulong ReadULong(this NetworkReader reader) => reader.ReadBlittable<ulong>(); public static ulong ReadULong(this NetworkReader reader) => Compression.DecompressVarUInt(reader);
public static ulong? ReadULongNullable(this NetworkReader reader) => reader.ReadBlittableNullable<ulong>(); public static ulong? ReadULongNullable(this NetworkReader reader)
{
return reader.ReadBool() ? Compression.DecompressVarUInt(reader) : default;
}
public static float ReadFloat(this NetworkReader reader) => reader.ReadBlittable<float>(); public static float ReadFloat(this NetworkReader reader) => reader.ReadBlittable<float>();
public static float? ReadFloatNullable(this NetworkReader reader) => reader.ReadBlittableNullable<float>(); public static float? ReadFloatNullable(this NetworkReader reader) => reader.ReadBlittableNullable<float>();

View File

@ -28,17 +28,38 @@ public static class NetworkWriterExtensions
public static void WriteUShort(this NetworkWriter writer, ushort value) => writer.WriteBlittable(value); public static void WriteUShort(this NetworkWriter writer, ushort value) => writer.WriteBlittable(value);
public static void WriteUShortNullable(this NetworkWriter writer, ushort? value) => writer.WriteBlittableNullable(value); public static void WriteUShortNullable(this NetworkWriter writer, ushort? value) => writer.WriteBlittableNullable(value);
public static void WriteInt(this NetworkWriter writer, int value) => writer.WriteBlittable(value); // integer bandwidth optimization: write all ints as varint!
public static void WriteIntNullable(this NetworkWriter writer, int? value) => writer.WriteBlittableNullable(value); // reduces bandwidth for almost all integers.
// increaes bandwidth for very few large integers like hashes.
// => very much worth it for Mirror (see Benchmarks)
// => very much worth it for users (they won't have to compress manually)
public static void WriteInt(this NetworkWriter writer, int value) => Compression.CompressVarInt(writer, value);
public static void WriteIntNullable(this NetworkWriter writer, int? value)
{
writer.WriteBool(value.HasValue);
if (value.HasValue) WriteInt(writer, value.Value);
}
public static void WriteUInt(this NetworkWriter writer, uint value) => writer.WriteBlittable(value); public static void WriteUInt(this NetworkWriter writer, uint value) => Compression.CompressVarUInt(writer, value);
public static void WriteUIntNullable(this NetworkWriter writer, uint? value) => writer.WriteBlittableNullable(value); public static void WriteUIntNullable(this NetworkWriter writer, uint? value)
{
writer.WriteBool(value.HasValue);
if (value.HasValue) WriteUInt(writer, value.Value);
}
public static void WriteLong(this NetworkWriter writer, long value) => writer.WriteBlittable(value); public static void WriteLong(this NetworkWriter writer, long value) => Compression.CompressVarInt(writer, value);
public static void WriteLongNullable(this NetworkWriter writer, long? value) => writer.WriteBlittableNullable(value); public static void WriteLongNullable(this NetworkWriter writer, long? value)
{
writer.WriteBool(value.HasValue);
if (value.HasValue) WriteLong(writer, value.Value);
}
public static void WriteULong(this NetworkWriter writer, ulong value) => writer.WriteBlittable(value); public static void WriteULong(this NetworkWriter writer, ulong value) => Compression.CompressVarUInt(writer, value);
public static void WriteULongNullable(this NetworkWriter writer, ulong? value) => writer.WriteBlittableNullable(value); public static void WriteULongNullable(this NetworkWriter writer, ulong? value)
{
writer.WriteBool(value.HasValue);
if (value.HasValue) WriteULong(writer, value.Value);
}
public static void WriteFloat(this NetworkWriter writer, float value) => writer.WriteBlittable(value); public static void WriteFloat(this NetworkWriter writer, float value) => writer.WriteBlittable(value);
public static void WriteFloatNullable(this NetworkWriter writer, float? value) => writer.WriteBlittableNullable(value); public static void WriteFloatNullable(this NetworkWriter writer, float? value) => writer.WriteBlittableNullable(value);

View File

@ -318,7 +318,6 @@ public static void CompressVarUInt(NetworkWriter writer, ulong value)
{ {
// straight forward implementation: // straight forward implementation:
// keep this for understanding & debugging. // keep this for understanding & debugging.
/*
if (value <= 240) if (value <= 240)
{ {
writer.WriteByte((byte)value); writer.WriteByte((byte)value);
@ -400,11 +399,12 @@ public static void CompressVarUInt(NetworkWriter writer, ulong value)
writer.WriteByte((byte)((value >> 48) & 0xFF)); writer.WriteByte((byte)((value >> 48) & 0xFF));
writer.WriteByte((byte)((value >> 56) & 0xFF)); writer.WriteByte((byte)((value >> 56) & 0xFF));
} }
*/
// DISABLED: WriteInt() always calls WriteVarInt, so we can't recurse to WriteInt here
// faster implementation writes multiple bytes at once. // faster implementation writes multiple bytes at once.
// avoids extra Space, WriteBlittable overhead. // avoids extra Space, WriteBlittable overhead.
// VarInt is in hot path, performance matters here. // VarInt is in hot path, performance matters here.
/*
if (value <= 240) if (value <= 240)
{ {
byte a = (byte)value; byte a = (byte)value;
@ -474,7 +474,7 @@ public static void CompressVarUInt(NetworkWriter writer, ulong value)
{ {
writer.WriteByte(255); writer.WriteByte(255);
writer.WriteULong(value); writer.WriteULong(value);
} }*/
} }
// zigzag encoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba // zigzag encoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba