feat: added benchmarks
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Google.Protobuf;
|
||||
using UnityEngine;
|
||||
|
||||
public class BenchmarkRunner : MonoBehaviour
|
||||
{
|
||||
private const int N = 10_000;
|
||||
private const int Warmup = 1_000;
|
||||
|
||||
private unsafe void Start()
|
||||
{
|
||||
var apMsg = new Arpack.Messages.MoveMessage
|
||||
{
|
||||
Position = new Arpack.Messages.Vector3 { X = 100, Y = -50, Z = 0 },
|
||||
Velocity = new float[] { 1.5f, -2.5f, 0f },
|
||||
Waypoints = new Arpack.Messages.Vector3[]
|
||||
{
|
||||
new Arpack.Messages.Vector3 { X = 10, Y = 20, Z = 0 },
|
||||
new Arpack.Messages.Vector3 { X = -10, Y = 0, Z = 100 },
|
||||
},
|
||||
PlayerID = 999,
|
||||
Active = true,
|
||||
Visible = false,
|
||||
Ghost = true,
|
||||
Name = "PlayerOne",
|
||||
};
|
||||
|
||||
var pbMsg = new Benchproto.MoveMessage
|
||||
{
|
||||
Position = new Benchproto.Vector3 { X = 100, Y = -50, Z = 0 },
|
||||
PlayerId = 999,
|
||||
Active = true,
|
||||
Visible = false,
|
||||
Ghost = true,
|
||||
Name = "PlayerOne",
|
||||
};
|
||||
pbMsg.Velocity.AddRange(new float[] { 1.5f, -2.5f, 0f });
|
||||
pbMsg.Waypoints.Add(new Benchproto.Vector3 { X = 10, Y = 20, Z = 0 });
|
||||
pbMsg.Waypoints.Add(new Benchproto.Vector3 { X = -10, Y = 0, Z = 100 });
|
||||
|
||||
byte[] apBuf = new byte[256];
|
||||
int apWireSize;
|
||||
fixed (byte* ptr = apBuf) { apWireSize = apMsg.Serialize(ptr); }
|
||||
|
||||
byte[] apBytes = new byte[apWireSize];
|
||||
Array.Copy(apBuf, apBytes, apWireSize);
|
||||
|
||||
byte[] pbBytes = pbMsg.ToByteArray();
|
||||
int pbWireSize = pbBytes.Length;
|
||||
byte[] protoOutputBuf = new byte[256];
|
||||
|
||||
// Warmup (JIT)
|
||||
for (int i = 0; i < Warmup; i++)
|
||||
{
|
||||
fixed (byte* ptr = apBuf) { apMsg.Serialize(ptr); }
|
||||
fixed (byte* ptr = apBytes) { Arpack.Messages.MoveMessage.Deserialize(ptr, out _); }
|
||||
_ = pbMsg.ToByteArray();
|
||||
_ = Benchproto.MoveMessage.Parser.ParseFrom(pbBytes);
|
||||
var cos = new CodedOutputStream(protoOutputBuf);
|
||||
pbMsg.WriteTo(cos);
|
||||
cos.Flush();
|
||||
}
|
||||
|
||||
Stopwatch sw;
|
||||
long gcBefore, gcAfter;
|
||||
|
||||
// ArPack Serialize
|
||||
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
|
||||
gcBefore = GC.GetTotalMemory(false);
|
||||
sw = Stopwatch.StartNew();
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
fixed (byte* ptr = apBuf) { apMsg.Serialize(ptr); }
|
||||
}
|
||||
sw.Stop();
|
||||
gcAfter = GC.GetTotalMemory(false);
|
||||
Log("ArPack Serialize ", sw, N, gcAfter - gcBefore);
|
||||
|
||||
// ArPack Deserialize
|
||||
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
|
||||
gcBefore = GC.GetTotalMemory(false);
|
||||
sw = Stopwatch.StartNew();
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
fixed (byte* ptr = apBytes) { Arpack.Messages.MoveMessage.Deserialize(ptr, out _); }
|
||||
}
|
||||
sw.Stop();
|
||||
gcAfter = GC.GetTotalMemory(false);
|
||||
Log("ArPack Deserialize ", sw, N, gcAfter - gcBefore);
|
||||
|
||||
// Proto Serialize (alloc)
|
||||
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
|
||||
gcBefore = GC.GetTotalMemory(false);
|
||||
sw = Stopwatch.StartNew();
|
||||
byte[] pbOut = null;
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
pbOut = pbMsg.ToByteArray();
|
||||
}
|
||||
sw.Stop();
|
||||
gcAfter = GC.GetTotalMemory(false);
|
||||
Log("Proto Serialize (alloc) ", sw, N, gcAfter - gcBefore);
|
||||
_ = pbOut;
|
||||
|
||||
// Proto Deserialize (alloc)
|
||||
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
|
||||
gcBefore = GC.GetTotalMemory(false);
|
||||
sw = Stopwatch.StartNew();
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
_ = Benchproto.MoveMessage.Parser.ParseFrom(pbBytes);
|
||||
}
|
||||
sw.Stop();
|
||||
gcAfter = GC.GetTotalMemory(false);
|
||||
Log("Proto Deserialize (alloc)", sw, N, gcAfter - gcBefore);
|
||||
|
||||
// Proto Serialize (reuse buffer)
|
||||
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
|
||||
gcBefore = GC.GetTotalMemory(false);
|
||||
sw = Stopwatch.StartNew();
|
||||
for (int i = 0; i < N; i++)
|
||||
{
|
||||
var cos = new CodedOutputStream(protoOutputBuf);
|
||||
pbMsg.WriteTo(cos);
|
||||
cos.Flush();
|
||||
}
|
||||
sw.Stop();
|
||||
gcAfter = GC.GetTotalMemory(false);
|
||||
Log("Proto Serialize (reuse) ", sw, N, gcAfter - gcBefore);
|
||||
|
||||
UnityEngine.Debug.Log($"[Bench] Wire sizes — ArPack: {apWireSize} bytes | Protobuf: {pbWireSize} bytes");
|
||||
}
|
||||
|
||||
private static void Log(string label, Stopwatch sw, int n, long gcDelta)
|
||||
{
|
||||
double nsPerOp = sw.Elapsed.TotalMilliseconds * 1_000_000.0 / n;
|
||||
long bPerOp = Math.Max(0, gcDelta) / n;
|
||||
UnityEngine.Debug.Log($"[Bench] {label}: {nsPerOp,8:F1} ns/op | {bPerOp,6} B/op");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user