Skip to content

Instantly share code, notes, and snippets.

@arturaz
Created January 24, 2023 20:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arturaz/85f88dc97a7888914e442aa8be4a0fa5 to your computer and use it in GitHub Desktop.
Save arturaz/85f88dc97a7888914e442aa8be4a0fa5 to your computer and use it in GitHub Desktop.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using UnityEngine;
using Debug = UnityEngine.Debug;
public unsafe class TestInVsPointer : MonoBehaviour
{
// 8 * 8 = 64 bytes
readonly struct Large3 { readonly ulong p1, p2, p3, p4, p5, p6, p7, p8; }
// 8 * 64 = 512 bytes
readonly struct Large2 { readonly Large3 p1, p2, p3, p4, p5, p6, p7, p8; }
// 8 * 512 = 4kb
readonly struct Large1 { readonly Large2 p1, p2, p3, p4, p5, p6, p7, p8; }
// 8 * 4kb = 32kb
struct Large { public Large1 p1; }
readonly struct LargeRO { readonly Large1 p1; }
static Large large;
static LargeRO largeRO;
delegate void ActionPtr<A>(A* ptr) where A : unmanaged;
// Start is called before the first frame update
void Start() {
fixed (Large* largePtr = &large) {
fixed (LargeRO* largeROPtr = &largeRO) {
benchmark($"large (size={Marshal.SizeOf(large)})", 0, _ => take(large));
benchmark($"large in (size={Marshal.SizeOf(large)})", 0, _ => takeIn(large));
benchmark($"large ptr (size={Marshal.SizeOf(large)})", largePtr, takePtr);
benchmark($"largeRO (size={Marshal.SizeOf(largeRO)})", 0, _ => take(largeRO));
benchmark($"largeRO in (size={Marshal.SizeOf(largeRO)})", 0, _ => takeIn(largeRO));
benchmark($"largeRO ptr (size={Marshal.SizeOf(largeRO)})", largeROPtr, takePtr);
Debug.Log(sb.ToString());
}
}
}
void take<A>(A a) {
}
void takeIn<A>(in A a) {
}
void takePtr<A>(A* a) where A : unmanaged {
}
static readonly StringBuilder sb = new StringBuilder();
static readonly Stopwatch sw = new Stopwatch();
const int TIMES = 5_000_000;
static void benchmark<Data>(string name, Data data, Action<Data> action) {
sw.Restart();
for (var idx = 0; idx < TIMES; idx++) {
action(data);
}
sw.Stop();
var perRun = sw.Elapsed.TotalMilliseconds / TIMES;
sb.Append($"{name} took total={sw.Elapsed}, per run={perRun:F}ms\n");
}
static void benchmark<Data>(string name, Data* data, ActionPtr<Data> action) where Data : unmanaged {
sw.Restart();
for (var idx = 0; idx < TIMES; idx++) {
action(data);
}
sw.Stop();
var perRun = sw.Elapsed.TotalMilliseconds / TIMES;
sb.Append($"{name} took total={sw.Elapsed}, per run={perRun:F}ms\n");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment