perf: Pack small 32 bit negatives efficiently

This commit is contained in:
Paul Pacheco 2019-03-30 13:13:19 -05:00
parent 3ec7f6c1d0
commit 480af1aa6c
8 changed files with 76 additions and 22 deletions

View File

@ -229,7 +229,7 @@ bool WriteParameters(NetworkWriter writer)
if (par.type == AnimatorControllerParameterType.Int) if (par.type == AnimatorControllerParameterType.Int)
{ {
int newIntValue = animator.GetInteger(par.nameHash); int newIntValue = animator.GetInteger(par.nameHash);
writer.WritePackedUInt32((uint)newIntValue); writer.WritePackedInt32(newIntValue);
} }
else if (par.type == AnimatorControllerParameterType.Float) else if (par.type == AnimatorControllerParameterType.Float)
{ {
@ -256,7 +256,7 @@ void ReadParameters(NetworkReader reader)
AnimatorControllerParameter par = parameters[i]; AnimatorControllerParameter par = parameters[i];
if (par.type == AnimatorControllerParameterType.Int) if (par.type == AnimatorControllerParameterType.Int)
{ {
int newIntValue = (int)reader.ReadPackedUInt32(); int newIntValue = reader.ReadPackedInt32();
animator.SetInteger(par.nameHash, newIntValue); animator.SetInteger(par.nameHash, newIntValue);
} }
else if (par.type == AnimatorControllerParameterType.Float) else if (par.type == AnimatorControllerParameterType.Float)

View File

@ -462,7 +462,7 @@ void DeserializeField(FieldDefinition syncVar, ILProcessor serWorker, MethodDefi
// read id and store in a local variable // read id and store in a local variable
serWorker.Append(serWorker.Create(OpCodes.Ldarg_1)); serWorker.Append(serWorker.Create(OpCodes.Ldarg_1));
serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkReaderReadPacked32)); serWorker.Append(serWorker.Create(OpCodes.Call, Weaver.NetworkReaderReadPackedUInt32));
serWorker.Append(serWorker.Create(OpCodes.Stloc, tmpValue)); serWorker.Append(serWorker.Create(OpCodes.Stloc, tmpValue));
if (foundMethod != null) if (foundMethod != null)

View File

@ -101,10 +101,12 @@ class Weaver
public static MethodReference NetworkServerGetLocalClientActive; public static MethodReference NetworkServerGetLocalClientActive;
public static MethodReference NetworkClientGetActive; public static MethodReference NetworkClientGetActive;
public static MethodReference UBehaviourIsServer; public static MethodReference UBehaviourIsServer;
public static MethodReference NetworkReaderReadPacked32; public static MethodReference NetworkReaderReadPackedUInt32;
public static MethodReference NetworkReaderReadPackedInt32;
public static MethodReference NetworkReaderReadPacked64; public static MethodReference NetworkReaderReadPacked64;
public static MethodReference NetworkReaderReadByte; public static MethodReference NetworkReaderReadByte;
public static MethodReference NetworkWriterWritePacked32; public static MethodReference NetworkWriterWritePackedUInt32;
public static MethodReference NetworkWriterWritePackedInt32;
public static MethodReference NetworkWriterWritePacked64; public static MethodReference NetworkWriterWritePacked64;
public static MethodReference NetworkReadUInt16; public static MethodReference NetworkReadUInt16;
@ -1101,11 +1103,13 @@ static void SetupTargetTypes()
NetworkWriterWriteInt32 = Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", int32Type); NetworkWriterWriteInt32 = Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", int32Type);
NetworkWriterWriteInt16 = Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", int16Type); NetworkWriterWriteInt16 = Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", int16Type);
NetworkReaderReadPacked32 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedUInt32"); NetworkReaderReadPackedUInt32 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedUInt32");
NetworkReaderReadPackedInt32 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedInt32");
NetworkReaderReadPacked64 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedUInt64"); NetworkReaderReadPacked64 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadPackedUInt64");
NetworkReaderReadByte = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadByte"); NetworkReaderReadByte = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadByte");
NetworkWriterWritePacked32 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedUInt32"); NetworkWriterWritePackedUInt32 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedUInt32");
NetworkWriterWritePackedInt32 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedInt32");
NetworkWriterWritePacked64 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedUInt64"); NetworkWriterWritePacked64 = Resolvers.ResolveMethod(NetworkWriterType, CurrentAssembly, "WritePackedUInt64");
NetworkReadUInt16 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadUInt16"); NetworkReadUInt16 = Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadUInt16");
@ -1182,8 +1186,8 @@ static void SetupReadFunctions()
{ stringType.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadString") }, { stringType.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadString") },
{ int64Type.FullName, NetworkReaderReadPacked64 }, { int64Type.FullName, NetworkReaderReadPacked64 },
{ uint64Type.FullName, NetworkReaderReadPacked64 }, { uint64Type.FullName, NetworkReaderReadPacked64 },
{ int32Type.FullName, NetworkReaderReadPacked32 }, { int32Type.FullName, NetworkReaderReadPackedInt32 },
{ uint32Type.FullName, NetworkReaderReadPacked32 }, { uint32Type.FullName, NetworkReaderReadPackedUInt32 },
{ int16Type.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadInt16") }, { int16Type.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadInt16") },
{ uint16Type.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadUInt16") }, { uint16Type.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadUInt16") },
{ byteType.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadByte") }, { byteType.FullName, Resolvers.ResolveMethod(NetworkReaderType, CurrentAssembly, "ReadByte") },
@ -1220,8 +1224,8 @@ static void SetupWriteFunctions()
{ stringType.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", stringType) }, { stringType.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", stringType) },
{ int64Type.FullName, NetworkWriterWritePacked64 }, { int64Type.FullName, NetworkWriterWritePacked64 },
{ uint64Type.FullName, NetworkWriterWritePacked64 }, { uint64Type.FullName, NetworkWriterWritePacked64 },
{ int32Type.FullName, NetworkWriterWritePacked32 }, { int32Type.FullName, NetworkWriterWritePackedInt32 },
{ uint32Type.FullName, NetworkWriterWritePacked32 }, { uint32Type.FullName, NetworkWriterWritePackedUInt32 },
{ int16Type.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", int16Type) }, { int16Type.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", int16Type) },
{ uint16Type.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", uint16Type) }, { uint16Type.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", uint16Type) },
{ byteType.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", byteType) }, { byteType.FullName, Resolvers.ResolveMethodWithArg(NetworkWriterType, CurrentAssembly, "Write", byteType) },

View File

@ -99,12 +99,12 @@ public IntegerMessage(int v)
public override void Deserialize(NetworkReader reader) public override void Deserialize(NetworkReader reader)
{ {
value = (int)reader.ReadPackedUInt32(); value = reader.ReadPackedInt32();
} }
public override void Serialize(NetworkWriter writer) public override void Serialize(NetworkWriter writer)
{ {
writer.WritePackedUInt32((uint)value); writer.WritePackedInt32(value);
} }
} }

View File

@ -57,6 +57,13 @@ public byte[] ReadBytesAndSize()
return null; return null;
} }
// zigzag decoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba
public int ReadPackedInt32()
{
uint data = ReadPackedUInt32();
return (int)((data >> 1) ^ -(data & 1));
}
// http://sqlite.org/src4/doc/trunk/www/varint.wiki // http://sqlite.org/src4/doc/trunk/www/varint.wiki
// NOTE: big endian. // NOTE: big endian.
public uint ReadPackedUInt32() public uint ReadPackedUInt32()
@ -145,12 +152,12 @@ public Vector4 ReadVector4()
public Vector2Int ReadVector2Int() public Vector2Int ReadVector2Int()
{ {
return new Vector2Int((int)ReadPackedUInt32(), (int)ReadPackedUInt32()); return new Vector2Int(ReadPackedInt32(), ReadPackedInt32());
} }
public Vector3Int ReadVector3Int() public Vector3Int ReadVector3Int()
{ {
return new Vector3Int((int)ReadPackedUInt32(), (int)ReadPackedUInt32(), (int)ReadPackedUInt32()); return new Vector3Int(ReadPackedInt32(), ReadPackedInt32(), ReadPackedInt32());
} }
public Color ReadColor() public Color ReadColor()

View File

@ -100,6 +100,13 @@ public void WriteBytesAndSize(byte[] buffer)
WriteBytesAndSize(buffer, 0, buffer != null ? buffer.Length : 0); WriteBytesAndSize(buffer, 0, buffer != null ? buffer.Length : 0);
} }
// zigzag encoding https://gist.github.com/mfuerstenau/ba870a29e16536fdbaba
public void WritePackedInt32(int i)
{
uint zigzagged = (uint)((i >> 31) ^ (i << 1));
WritePackedUInt32(zigzagged);
}
// http://sqlite.org/src4/doc/trunk/www/varint.wiki // http://sqlite.org/src4/doc/trunk/www/varint.wiki
public void WritePackedUInt32(uint value) public void WritePackedUInt32(uint value)
{ {
@ -216,15 +223,15 @@ public void Write(Vector4 value)
public void Write(Vector2Int value) public void Write(Vector2Int value)
{ {
WritePackedUInt32((uint)value.x); WritePackedInt32(value.x);
WritePackedUInt32((uint)value.y); WritePackedInt32(value.y);
} }
public void Write(Vector3Int value) public void Write(Vector3Int value)
{ {
WritePackedUInt32((uint)value.x); WritePackedInt32(value.x);
WritePackedUInt32((uint)value.y); WritePackedInt32(value.y);
WritePackedUInt32((uint)value.z); WritePackedInt32(value.z);
} }
public void Write(Color value) public void Write(Color value)

View File

@ -19,8 +19,8 @@ public class SyncListFloat : SyncList<float>
public class SyncListInt : SyncList<int> public class SyncListInt : SyncList<int>
{ {
protected override void SerializeItem(NetworkWriter writer, int item) => writer.WritePackedUInt32((uint)item); protected override void SerializeItem(NetworkWriter writer, int item) => writer.WritePackedInt32(item);
protected override int DeserializeItem(NetworkReader reader) => (int)reader.ReadPackedUInt32(); protected override int DeserializeItem(NetworkReader reader) => reader.ReadPackedInt32();
} }
public class SyncListUInt : SyncList<uint> public class SyncListUInt : SyncList<uint>

View File

@ -79,6 +79,42 @@ public void TestPackedUInt32()
Assert.That(reader.ReadPackedUInt32(), Is.EqualTo(uint.MaxValue)); Assert.That(reader.ReadPackedUInt32(), Is.EqualTo(uint.MaxValue));
} }
[Test]
public void TestPackedInt32()
{
NetworkWriter writer = new NetworkWriter();
writer.WritePackedInt32(0);
writer.WritePackedInt32(234);
writer.WritePackedInt32(2284);
writer.WritePackedInt32(67821);
writer.WritePackedInt32(16777210);
writer.WritePackedInt32(16777219);
writer.WritePackedInt32(int.MaxValue);
writer.WritePackedInt32(-1);
writer.WritePackedInt32(-234);
writer.WritePackedInt32(-2284);
writer.WritePackedInt32(-67821);
writer.WritePackedInt32(-16777210);
writer.WritePackedInt32(-16777219);
writer.WritePackedInt32(int.MinValue);
NetworkReader reader = new NetworkReader(writer.ToArray());
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(0));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(234));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(2284));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(67821));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(16777210));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(16777219));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(int.MaxValue));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-1));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-234));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-2284));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-67821));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-16777210));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(-16777219));
Assert.That(reader.ReadPackedInt32(), Is.EqualTo(int.MinValue));
}
[Test] [Test]
public void TestPackedUInt64() public void TestPackedUInt64()
{ {