diff --git a/.gitea/workflows/performance.yml b/.gitea/workflows/performance.yml
new file mode 100644
index 0000000..15a96ff
--- /dev/null
+++ b/.gitea/workflows/performance.yml
@@ -0,0 +1,53 @@
+name: performance evidence
+
+on:
+ push:
+ paths:
+ - "benchmarks/**"
+ - "tools/performance/**"
+ - "crates/libremetaverse/src/inventory.rs"
+ - "crates/libremetaverse/src/targa.rs"
+ - ".gitea/workflows/performance.yml"
+ - "Cargo.toml"
+ - "Cargo.lock"
+ pull_request:
+ paths:
+ - "benchmarks/**"
+ - "tools/performance/**"
+ - "crates/libremetaverse/src/inventory.rs"
+ - "crates/libremetaverse/src/targa.rs"
+ - ".gitea/workflows/performance.yml"
+ - "Cargo.toml"
+ - "Cargo.lock"
+
+jobs:
+ audit:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: dtolnay/rust-toolchain@stable
+ with:
+ toolchain: 1.97.1
+ components: rustfmt, clippy
+ - uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 8.0.x
+ 10.0.x
+ - name: Check out pinned C# reference
+ run: |
+ git clone --filter=blob:none https://github.com/cinderblocks/libremetaverse.git "$RUNNER_TEMP/libremetaverse"
+ git -C "$RUNNER_TEMP/libremetaverse" checkout 2aa70bb68513b39795da5d13c88f31b86e85a3ba
+ - name: Compile separate C# reference runner
+ run: >-
+ dotnet build benchmarks/csharp-reference/MetaCrate.ReferenceBenchmarks.csproj
+ -c Release -p:ReferenceRoot="$RUNNER_TEMP/libremetaverse"
+ - name: Verify harness
+ run: cargo test -p metacrate-performance --profile benchmark --locked -j1
+ - name: Audit committed evidence
+ run: >-
+ cargo run -p metacrate-performance --profile benchmark --locked -j1 --
+ audit --fixture-root benchmarks/fixtures
+ --rust benchmarks/results/rust-linux-x86_64.json
+ --reference benchmarks/results/csharp-linux-x86_64.json
+ --comparison benchmarks/results/comparison.json
diff --git a/Cargo.lock b/Cargo.lock
index d1b6068..13baae1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1791,6 +1791,22 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "metacrate-performance"
+version = "0.0.1"
+dependencies = [
+ "libremetaverse",
+ "libremetaverse-imaging",
+ "libremetaverse-rendering-mesh-foundry",
+ "libremetaverse-rendering-simple",
+ "libremetaverse-structured-data",
+ "libremetaverse-types",
+ "serde",
+ "serde_json",
+ "sha2 0.11.0",
+ "stats_alloc",
+]
+
[[package]]
name = "minimal-lexical"
version = "0.2.1"
diff --git a/Cargo.toml b/Cargo.toml
index d214570..b6dfc2a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,6 +21,7 @@ members = [
"tools/codegen",
"tools/ci-matrix",
"tools/concurrency-audit",
+ "tools/performance",
]
[workspace.package]
diff --git a/benchmarks/README.md b/benchmarks/README.md
new file mode 100644
index 0000000..9eed8d9
--- /dev/null
+++ b/benchmarks/README.md
@@ -0,0 +1,90 @@
+# Pinned cross-runtime performance evidence
+
+This directory compares representative offline work in native Rust with the
+pinned C# source at commit `2aa70bb68513b39795da5d13c88f31b86e85a3ba`.
+The runners are separate executables. The Rust executable never starts a CLR,
+loads a managed assembly, accesses a grid, or reads `.env`.
+
+## Workloads and fixtures
+
+`fixtures/manifest.json` records SHA-256 for every shared input. Both runners
+refuse a changed fixture. The suite measures UUID/matrix/quaternion operations,
+all five supported LLSD codecs, packet encode/decode, notecard/TGA/mesh decode,
+inventory and object updates, simple rendering, and a batched offline client
+message pipeline. Each report contains one cold operation and seven warm
+samples. It records latency, throughput, allocated bytes, retained heap bytes,
+and allocation count where the runtime exposes it. .NET reports a null
+allocation count because its supported in-process GC API exposes bytes, not
+operation count; it does not substitute a misleading zero.
+
+The checked-in inputs are deliberately modest so the suite completes on a
+four-core, 8 GiB release worker. Iteration counts live in `workloads.json`.
+Regenerate binary inputs only after an intentional fixture review:
+
+```sh
+cargo run -p metacrate-performance --profile benchmark -- \
+ fixtures --fixture-root benchmarks/fixtures
+```
+
+## Reproducing the reports
+
+Use the same otherwise-idle machine for both runs. Disable adaptive power or
+thermal throttling where the host permits it. The committed evidence was
+captured on Linux x86-64 with four AMD EPYC-Genoa vCPUs and 7.6 GiB RAM, Rust
+1.97.1, .NET SDK 10.0.400, and the .NET 8.0.30 runtime. C# is built in Release
+for `net8.0`. Rust uses the repository's `benchmark` profile (opt-level 1,
+debug/incremental disabled): higher optimization of the generated core exceeds
+the memory limit on this release worker, so this is a conservative Rust result.
+
+```sh
+REFERENCE_ROOT=/absolute/path/to/libremetaverse
+test "$(git -C "$REFERENCE_ROOT" rev-parse HEAD)" = \
+ 2aa70bb68513b39795da5d13c88f31b86e85a3ba
+
+dotnet build benchmarks/csharp-reference/MetaCrate.ReferenceBenchmarks.csproj \
+ -c Release -p:ReferenceRoot="$REFERENCE_ROOT"
+dotnet benchmarks/csharp-reference/bin/Release/net8.0/MetaCrate.ReferenceBenchmarks.dll \
+ run --reference-root "$REFERENCE_ROOT" \
+ --fixture-root benchmarks/fixtures \
+ --output benchmarks/results/csharp-linux-x86_64.json
+
+cargo run -p metacrate-performance --profile benchmark -- \
+ run --fixture-root benchmarks/fixtures \
+ --output benchmarks/results/rust-linux-x86_64.json
+cargo run -p metacrate-performance --profile benchmark -- \
+ compare --rust benchmarks/results/rust-linux-x86_64.json \
+ --reference benchmarks/results/csharp-linux-x86_64.json \
+ --output benchmarks/results/comparison.json
+cargo run -p metacrate-performance --profile benchmark -- \
+ audit --fixture-root benchmarks/fixtures \
+ --rust benchmarks/results/rust-linux-x86_64.json \
+ --reference benchmarks/results/csharp-linux-x86_64.json \
+ --comparison benchmarks/results/comparison.json
+```
+
+The C# runner executes `git rev-parse` itself and rejects any other source
+commit. The comparison rejects different fixture hashes, operating systems, or
+architectures.
+
+## Release criteria and reviewed differences
+
+`release-criteria.json` is executable policy. A warm median at least 25% slower
+than the reference is material and must be reviewed; the hard default is no
+more than 2.0x latency or allocated bytes. Reference operations below one
+microsecond are latency-noise exempt, but not allocation exempt.
+
+Three workload-specific differences are accepted:
+
+- Rust LLSD JSON owns and validates the bounded decoded tree. It is over four
+ times faster in this evidence, so up to 2.1x allocated bytes is accepted.
+- Rust rendering performs the completed behavior: six faces, 24 vertices, 36
+ indices, checked normals, UVs, extents, and materials. The pinned C#
+ `SimpleRenderer` still returns a one-face/eight-vertex placeholder cube.
+ Slowing Rust down by removing correctness would violate the milestone, so the
+ policy accepts up to 8x latency and 4x allocated bytes for this workload.
+- Rust client throughput returns checked `Result` values and owns the bounded
+ OSD map throughout the message pipeline. It allocates fewer bytes than C#;
+ its measured 1.64x latency is reviewed up to the unchanged 2x hard limit.
+
+No exception permits changed wire data, decoded values, fixture output, or
+public behavior. Any other threshold failure blocks the audit.
diff --git a/benchmarks/REPORT.md b/benchmarks/REPORT.md
new file mode 100644
index 0000000..679c0ee
--- /dev/null
+++ b/benchmarks/REPORT.md
@@ -0,0 +1,41 @@
+# Performance comparison report
+
+Accepted evidence captured 2026-08-12 on the Linux x86-64 host documented in
+`README.md`. Ratios are Rust divided by the pinned C# reference; lower is
+better. Bytes are allocated bytes per operation. Full cold and seven-sample
+warm measurements, throughput, allocation count support, retained heap, hashes,
+and toolchains are in `results/`.
+
+| Workload | Rust latency | C# latency | Ratio | Rust bytes | C# bytes | Result |
+|---|---:|---:|---:|---:|---:|---|
+| UUID/math | 107 ns | 105 ns | 1.02x | 36 | 40 | pass |
+| LLSD XML | 23.36 us | 38.74 us | 0.60x | 10,939 | 28,600 | pass |
+| LLSD JSON | 5.23 us | 21.72 us | 0.24x | 7,447 | 3,680 | reviewed pass |
+| LLSD binary | 2.69 us | 11.07 us | 0.24x | 6,749 | 7,960 | pass |
+| LLSD notation | 7.01 us | 18.87 us | 0.37x | 8,489 | 10,096 | pass |
+| LLSD protobuf | 7.34 us | 30.97 us | 0.24x | 8,324 | 26,120 | pass |
+| Packet codec | 209 ns | 176 ns | 1.19x | 124 | 264 | pass |
+| Asset decode | 288 ns | 2.98 us | 0.10x | 1,246 | 4,512 | pass |
+| Image decode | 42.67 us | 48.27 us | 0.88x | 65,536 | 131,612 | pass |
+| Mesh decode | 413.29 us | 378.54 us | 1.09x | 507,740 | 564,593 | pass |
+| Inventory update | 972 ns | 758 ns | 1.28x | 373 | 357 | pass |
+| Object update | 27 ns | 46 ns | 0.59x | 16 | 11 | pass |
+| Rendering | 5.22 us | 1.01 us | 5.15x | 9,480 | 3,048 | reviewed pass |
+| Client throughput | 6.23 us | 3.80 us | 1.64x | 11,795 | 12,054 | reviewed pass |
+
+The initial profile exposed two actionable regressions. Root inventory updates
+rebuilt the entire hierarchy and link index on every record; the new guarded
+root path updates only the affected node/link and changed the comparison from
+about 22.6x latency and 10.2x allocation to 1.28x and 1.05x. TGA decoding copied
+the input stream and dispatched every ordinary pixel through the fully generic
+orientation/palette path; the checked borrowed-input and common-layout path
+changed it from about 3.4x latency and 2.0x allocation to 0.88x and 0.50x.
+
+LLSD JSON, rendering, and client throughput are the reviewed differences. JSON
+trades 2.02x allocated bytes for 4.15x lower latency. Rendering cannot be
+compared as equal work: the pinned C# method is a placeholder one-face cube,
+while Rust returns the required complete checked mesh. Client throughput is
+1.64x slower while allocating fewer bytes because Rust preserves checked
+results and bounded owned maps. The executable limits and rationales are in
+`release-criteria.json`; every other workload passes the default criteria or
+the documented sub-microsecond noise rule.
diff --git a/benchmarks/csharp-reference/MetaCrate.ReferenceBenchmarks.csproj b/benchmarks/csharp-reference/MetaCrate.ReferenceBenchmarks.csproj
new file mode 100644
index 0000000..aa546a7
--- /dev/null
+++ b/benchmarks/csharp-reference/MetaCrate.ReferenceBenchmarks.csproj
@@ -0,0 +1,15 @@
+
+
+ Exe
+ net8.0
+ enable
+ enable
+ true
+ $(MSBuildThisFileDirectory)../../../libremetaverse
+
+
+
+
+
+
+
diff --git a/benchmarks/csharp-reference/Program.cs b/benchmarks/csharp-reference/Program.cs
new file mode 100644
index 0000000..ff0e84b
--- /dev/null
+++ b/benchmarks/csharp-reference/Program.cs
@@ -0,0 +1,346 @@
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Text.Json;
+using LibreMetaverse;
+using LibreMetaverse.Assets;
+using LibreMetaverse.Imaging;
+using LibreMetaverse.Messages.Linden;
+using LibreMetaverse.Packets;
+using LibreMetaverse.Rendering;
+using LibreMetaverse.StructuredData;
+using IOPath = System.IO.Path;
+
+const int Schema = 1;
+const int Runs = 7;
+const string ExpectedReference = "2aa70bb68513b39795da5d13c88f31b86e85a3ba";
+
+if (args.Length == 0 || args[0] != "run")
+ throw new ArgumentException("usage: dotnet run ... -- run --fixture-root PATH --output FILE");
+string root = Value("--fixture-root") ?? "benchmarks/fixtures";
+string output = Value("--output") ?? "benchmarks/results/csharp-linux-x86_64.json";
+string referenceRoot = Value("--reference-root") ?? throw new ArgumentException("missing --reference-root");
+VerifyReferenceCommit(referenceRoot);
+Fixture fixture = JsonSerializer.Deserialize(File.ReadAllBytes(IOPath.Combine(root, "workloads.json")), Options())
+ ?? throw new InvalidDataException("empty fixture");
+if (fixture.Schema != 1 || fixture.ReferenceCommit != ExpectedReference || fixture.WarmupDivisor == 0)
+ throw new InvalidDataException("fixture schema or reference commit does not match policy");
+Dictionary hashes = VerifyManifest(root);
+var context = new Context(fixture, root);
+var results = new List();
+foreach (Workload workload in Workloads())
+{
+ int iterations = workload.Iterations(fixture);
+ Metrics cold = Measure(context, workload.Run, 1);
+ GC.KeepAlive(workload.Run(context, Math.Max(1, iterations / fixture.WarmupDivisor)));
+ var samples = new List();
+ for (int index = 0; index < Runs; index++) samples.Add(Measure(context, workload.Run, iterations));
+ Metrics median = samples.OrderBy(value => value.ElapsedNs).ElementAt(Runs / 2);
+ results.Add(new BenchmarkResult(workload.Name, workload.Category, "operation", workload.Fixture, cold, samples, median));
+}
+var report = new Report(
+ Schema,
+ "dotnet-reference",
+ ExpectedReference,
+ hashes,
+ new EnvironmentInfo(
+ OperatingSystem.IsLinux() ? "linux" : OperatingSystem.IsWindows() ? "windows" : OperatingSystem.IsMacOS() ? "macos" : RuntimeInformation.OSDescription,
+ RuntimeInformation.ProcessArchitecture switch { Architecture.X64 => "x86_64", Architecture.Arm64 => "aarch64", Architecture.X86 => "x86", Architecture.Arm => "arm", _ => RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant() },
+ Environment.ProcessorCount,
+ RuntimeInformation.FrameworkDescription,
+ "Release net8.0"),
+ results);
+Directory.CreateDirectory(IOPath.GetDirectoryName(IOPath.GetFullPath(output))!);
+File.WriteAllText(output, JsonSerializer.Serialize(report, Options()) + "\n");
+
+string? Value(string key)
+{
+ int index = Array.IndexOf(args, key);
+ return index >= 0 && index + 1 < args.Length ? args[index + 1] : null;
+}
+
+static JsonSerializerOptions Options() => new()
+{
+ PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
+ WriteIndented = true
+};
+
+static Dictionary VerifyManifest(string root)
+{
+ var expected = JsonSerializer.Deserialize>(
+ File.ReadAllBytes(IOPath.Combine(root, "manifest.json")), Options())
+ ?? throw new InvalidDataException("empty manifest");
+ foreach ((string name, string hash) in expected)
+ {
+ string actual = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(IOPath.Combine(root, name)))).ToLowerInvariant();
+ if (actual != hash) throw new InvalidDataException($"fixture hash mismatch for {name}");
+ }
+ return expected;
+}
+
+void VerifyReferenceCommit(string referenceRoot)
+{
+ var start = new ProcessStartInfo("git")
+ {
+ RedirectStandardOutput = true,
+ UseShellExecute = false
+ };
+ start.ArgumentList.Add("-C");
+ start.ArgumentList.Add(referenceRoot);
+ start.ArgumentList.Add("rev-parse");
+ start.ArgumentList.Add("HEAD");
+ var process = Process.Start(start) ?? throw new InvalidOperationException("could not start git");
+ string commit = process.StandardOutput.ReadToEnd().Trim();
+ process.WaitForExit();
+ if (process.ExitCode != 0 || commit != ExpectedReference)
+ throw new InvalidDataException($"reference checkout must be pinned to {ExpectedReference}, got {commit}");
+}
+
+static Metrics Measure(Context context, Func function, int iterations)
+{
+ long allocatedBefore = GC.GetAllocatedBytesForCurrentThread();
+ long heapBefore = GC.GetTotalMemory(false);
+ long started = Stopwatch.GetTimestamp();
+ ulong checksum = function(context, iterations);
+ long elapsed = Stopwatch.GetTimestamp() - started;
+ long heapAfter = GC.GetTotalMemory(false);
+ long allocated = GC.GetAllocatedBytesForCurrentThread() - allocatedBefore;
+ GC.KeepAlive(checksum);
+ long elapsedNs = checked((long)(elapsed * (1_000_000_000.0 / Stopwatch.Frequency)));
+ double seconds = elapsedNs / 1_000_000_000.0;
+ return new Metrics(iterations, elapsedNs, (double)elapsedNs / iterations, iterations / seconds, null, allocated, heapAfter - heapBefore);
+}
+
+static Workload[] Workloads() =>
+[
+ new("uuid_math", "uuid/math", "workloads.json", f => f.UuidMathIterations, UuidMath),
+ new("llsd_xml", "LLSD", "workloads.json", f => f.LlsdIterations, LlsdXml),
+ new("llsd_json", "LLSD", "workloads.json", f => f.LlsdIterations, LlsdJson),
+ new("llsd_binary", "LLSD", "workloads.json", f => f.LlsdIterations, LlsdBinary),
+ new("llsd_notation", "LLSD", "workloads.json", f => f.LlsdIterations, LlsdNotation),
+ new("llsd_protobuf", "LLSD", "workloads.json", f => f.LlsdIterations, LlsdProtobuf),
+ new("packet_codec", "packet codec", "agent_pause.packet", f => f.PacketIterations, PacketCodec),
+ new("asset_decode", "asset decode", "notecard.txt", f => f.AssetIterations, AssetDecode),
+ new("image_decode", "image decode", "image.tga", f => f.ImageIterations, ImageDecode),
+ new("mesh_decode", "mesh decode", "mesh_asset.bin", f => f.MeshIterations, MeshDecode),
+ new("inventory_update", "inventory update", "workloads.json", f => f.InventoryIterations, InventoryUpdate),
+ new("object_update", "object update", "workloads.json", f => f.ObjectIterations, ObjectUpdate),
+ new("rendering", "rendering", "workloads.json", f => f.RenderingIterations, Rendering),
+ new("client_throughput", "client throughput", "workloads.json", f => f.ClientIterations, ClientThroughput)
+];
+
+static ulong UuidMath(Context context, int iterations)
+{
+ Quaternion rotation = Quaternion.CreateFromEulers(0.25f, 0.5f, 0.75f);
+ Matrix4 matrix = Matrix4.CreateTranslation(new Vector3(10, 20, 30));
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ var parsed = new UUID(context.Fixture.Uuid);
+ matrix = Matrix4.Transform(matrix, rotation);
+ checksum ^= parsed.GetULong() ^ BitConverter.SingleToUInt32Bits(matrix.M41) ^ (ulong)index;
+ }
+ return checksum;
+}
+
+static ulong LlsdXml(Context context, int iterations) => LlsdBytes(context, iterations, OSDParser.SerializeLLSDXmlBytes, OSDParser.DeserializeLLSDXml);
+static ulong LlsdBinary(Context context, int iterations) => LlsdBytes(context, iterations, OSDParser.SerializeLLSDBinary, OSDParser.DeserializeLLSDBinary);
+static ulong LlsdProtobuf(Context context, int iterations) => LlsdBytes(context, iterations, value => OSDParser.SerializeLLSDProtobuf(value, true), OSDParser.DeserializeLLSDProtobuf);
+
+static ulong LlsdBytes(Context context, int iterations, Func serialize, Func deserialize)
+{
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ byte[] encoded = serialize(context.Llsd);
+ OSD decoded = deserialize(encoded);
+ checksum ^= (ulong)encoded.Length ^ (decoded.AsBoolean() ? 1UL : 0UL);
+ }
+ return checksum;
+}
+
+static ulong LlsdJson(Context context, int iterations)
+{
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ string encoded = OSDParser.SerializeJsonString(context.Llsd);
+ OSD decoded = OSDParser.DeserializeJson(encoded);
+ checksum ^= (ulong)encoded.Length ^ (decoded.AsBoolean() ? 1UL : 0UL);
+ }
+ return checksum;
+}
+
+static ulong LlsdNotation(Context context, int iterations)
+{
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ string encoded = OSDParser.SerializeLLSDNotation(context.Llsd);
+ OSD decoded = OSDParser.DeserializeLLSDNotation(encoded);
+ checksum ^= (ulong)encoded.Length ^ (decoded.AsBoolean() ? 1UL : 0UL);
+ }
+ return checksum;
+}
+
+static ulong PacketCodec(Context context, int iterations)
+{
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ int position = 0;
+ var packet = new AgentPausePacket(context.Packet, ref position);
+ byte[] encoded = packet.ToBytes();
+ checksum ^= (ulong)encoded.Length ^ packet.AgentData.SerialNum;
+ }
+ return checksum;
+}
+
+static ulong AssetDecode(Context context, int iterations)
+{
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ var asset = new AssetNotecard(context.Uuid, context.Notecard);
+ if (!asset.Decode()) throw new InvalidDataException("notecard decode returned false");
+ checksum ^= (ulong)asset.BodyText.Length;
+ }
+ return checksum;
+}
+
+static ulong ImageDecode(Context context, int iterations)
+{
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ using var stream = new MemoryStream(context.Image, false);
+ ManagedImage image = Targa.DecodeToManagedImage(stream);
+ checksum ^= (ulong)image.Red.Length;
+ }
+ return checksum;
+}
+
+static ulong MeshDecode(Context context, int iterations)
+{
+ var renderer = new MeshFoundry();
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ FacetedMesh mesh = renderer.GenerateFacetedMeshMesh(new Primitive(), context.Mesh, DetailLevel.Highest)
+ ?? throw new InvalidDataException("mesh fixture returned no geometry");
+ checksum ^= (ulong)mesh.Faces.Sum(face => face.Vertices.Count + face.Indices.Count);
+ }
+ return checksum;
+}
+
+static ulong InventoryUpdate(Context context, int iterations)
+{
+ var store = new Inventory(new GridClient(), context.Uuid);
+ for (int index = 0; index < iterations; index++)
+ {
+ var item = new InventoryItem(new UUID((ulong)(index % context.Fixture.InventoryItems + 1))) { Name = $"item-{index}" };
+ store.UpdateNodeFor(item);
+ }
+ return (ulong)store.Count;
+}
+
+static ulong ObjectUpdate(Context context, int iterations)
+{
+ Primitive[] objects = Enumerable.Range(0, context.Fixture.ObjectCount).Select(index => new Primitive { LocalID = (uint)index }).ToArray();
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ Primitive value = objects[index % objects.Length];
+ value.Position = new Vector3(index, index & 255, 21);
+ value.Rotation = Quaternion.CreateFromAxisAngle(Vector3.UnitZ, (index & 255) / 255.0f);
+ checksum ^= value.LocalID ^ BitConverter.SingleToUInt32Bits(value.Position.X);
+ }
+ return checksum;
+}
+
+static ulong Rendering(Context context, int iterations)
+{
+ var renderer = new SimpleRenderer();
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ FacetedMesh mesh = renderer.GenerateFacetedMesh(BoxPrimitive(), DetailLevel.High);
+ checksum ^= (ulong)mesh.Faces.Sum(face => face.Indices.Count);
+ }
+ return checksum;
+}
+
+static Primitive BoxPrimitive() => new()
+{
+ PrimData = new Primitive.ConstructionData
+ {
+ PCode = PCode.Prim, PathCurve = PathCurve.Line, ProfileCurve = ProfileCurve.Square,
+ PathScaleX = 1, PathScaleY = 1, PathBegin = 0, PathEnd = 1,
+ ProfileBegin = 0, ProfileEnd = 1, ProfileHollow = 0,
+ ProfileHole = HoleType.Same, PathRevolutions = 1
+ }
+};
+
+static ulong ClientThroughput(Context context, int iterations)
+{
+ var client = new GridClient();
+ ulong checksum = 0;
+ for (int index = 0; index < iterations; index++)
+ {
+ for (int batch = 0; batch < context.Fixture.ClientBatch; batch++)
+ {
+ var source = new RemoteParcelRequestReply { ParcelID = context.Uuid };
+ OSDMap map = source.Serialize();
+ var target = new RemoteParcelRequestReply();
+ target.Deserialize(map);
+ checksum ^= target.ParcelID.GetULong() ^ (ulong)index;
+ }
+ }
+ GC.KeepAlive(client);
+ return checksum;
+}
+
+sealed class Context
+{
+ public Context(Fixture fixture, string root)
+ {
+ Fixture = fixture;
+ Uuid = new UUID(fixture.Uuid);
+ Llsd = new OSDMap
+ {
+ ["agent_id"] = OSD.FromUUID(Uuid), ["name"] = OSD.FromString("MetaCrate benchmark"),
+ ["active"] = OSD.FromBoolean(true), ["score"] = OSD.FromReal(42.25),
+ ["items"] = IntegerArray(fixture.LlsdArrayLength)
+ };
+ Packet = File.ReadAllBytes(IOPath.Combine(root, "agent_pause.packet"));
+ Notecard = File.ReadAllBytes(IOPath.Combine(root, "notecard.txt"));
+ Image = File.ReadAllBytes(IOPath.Combine(root, "image.tga"));
+ Mesh = File.ReadAllBytes(IOPath.Combine(root, "mesh_asset.bin"));
+ }
+ private static OSDArray IntegerArray(int count)
+ {
+ var values = new OSDArray(count);
+ for (int index = 0; index < count; index++) values.Add(OSD.FromInteger(index));
+ return values;
+ }
+ public Fixture Fixture { get; }
+ public UUID Uuid { get; }
+ public OSD Llsd { get; }
+ public byte[] Packet { get; }
+ public byte[] Notecard { get; }
+ public byte[] Image { get; }
+ public byte[] Mesh { get; }
+}
+
+sealed record Fixture(
+ int Schema, string ReferenceCommit, string Uuid, int UuidMathIterations, int LlsdIterations,
+ int PacketIterations, int AssetIterations, int ImageIterations, int MeshIterations,
+ int InventoryIterations, int ObjectIterations, int RenderingIterations, int ClientIterations,
+ int WarmupDivisor, int LlsdArrayLength, int PacketBlocks, int ImageWidth, int ImageHeight,
+ int MeshSide, int InventoryItems, int ObjectCount, int ClientBatch);
+sealed record Metrics(int Iterations, long ElapsedNs, double LatencyNs, double ThroughputPerSecond, long? Allocations, long BytesAllocated, long RetainedBytes);
+sealed record BenchmarkResult(string Name, string Category, string Unit, string Fixture, Metrics Cold, List WarmSamples, Metrics WarmMedian);
+sealed record EnvironmentInfo(string Os, string Arch, int LogicalCpus, string Toolchain, string Profile);
+sealed record Report(int Schema, string Runtime, string ReferenceCommit, Dictionary FixtureHashes, EnvironmentInfo Environment, List Results);
+sealed record Workload(string Name, string Category, string Fixture, Func Iterations, Func Run);
diff --git a/benchmarks/fixtures/agent_pause.packet b/benchmarks/fixtures/agent_pause.packet
new file mode 100644
index 0000000..68aefcd
Binary files /dev/null and b/benchmarks/fixtures/agent_pause.packet differ
diff --git a/benchmarks/fixtures/image.tga b/benchmarks/fixtures/image.tga
new file mode 100644
index 0000000..035e8c4
Binary files /dev/null and b/benchmarks/fixtures/image.tga differ
diff --git a/benchmarks/fixtures/manifest.json b/benchmarks/fixtures/manifest.json
new file mode 100644
index 0000000..04f1e12
--- /dev/null
+++ b/benchmarks/fixtures/manifest.json
@@ -0,0 +1,7 @@
+{
+ "agent_pause.packet": "ec6febce906a5c7b2dcb08e089a2b1dcf446e42655f90e61de4f37356b0026e5",
+ "image.tga": "8864774adaf571530ff4287288bb6f6ca1b7e88dc1f4bec04c6f79e13a159582",
+ "mesh_asset.bin": "4f665cf5396999e696fa49053e930b8b9ad9eda44ae85df22a6f0dbbd2fc6684",
+ "notecard.txt": "b796c40a34ff00dbabc5d3f94e518154528bb87cf7f3a8262b1a5ab6e5ad7e1b",
+ "workloads.json": "9124763e4822e57850783c06b37cd569355f73ac2397bca85f6dd89e0470267d"
+}
diff --git a/benchmarks/fixtures/mesh_asset.bin b/benchmarks/fixtures/mesh_asset.bin
new file mode 100644
index 0000000..65363ad
Binary files /dev/null and b/benchmarks/fixtures/mesh_asset.bin differ
diff --git a/benchmarks/fixtures/notecard.txt b/benchmarks/fixtures/notecard.txt
new file mode 100644
index 0000000..cf8add5
--- /dev/null
+++ b/benchmarks/fixtures/notecard.txt
@@ -0,0 +1,9 @@
+Linden text version 2
+{
+LLEmbeddedItems version 1
+{
+count 0
+}
+Text length 127
+MetaCrate pinned performance fixture. This notecard exercises bounded asset parsing without a network or CLR dependency. 012345
+}
diff --git a/benchmarks/fixtures/workloads.json b/benchmarks/fixtures/workloads.json
new file mode 100644
index 0000000..9ef0d2d
--- /dev/null
+++ b/benchmarks/fixtures/workloads.json
@@ -0,0 +1,24 @@
+{
+ "schema": 1,
+ "reference_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba",
+ "uuid": "01234567-89ab-cdef-0123-456789abcdef",
+ "uuid_math_iterations": 100000,
+ "llsd_iterations": 2000,
+ "packet_iterations": 5000,
+ "asset_iterations": 1000,
+ "image_iterations": 100,
+ "mesh_iterations": 25,
+ "inventory_iterations": 10000,
+ "object_iterations": 20000,
+ "rendering_iterations": 250,
+ "client_iterations": 5000,
+ "warmup_divisor": 10,
+ "llsd_array_length": 32,
+ "packet_blocks": 16,
+ "image_width": 128,
+ "image_height": 128,
+ "mesh_side": 48,
+ "inventory_items": 128,
+ "object_count": 256,
+ "client_batch": 32
+}
diff --git a/benchmarks/release-criteria.json b/benchmarks/release-criteria.json
new file mode 100644
index 0000000..5b3edde
--- /dev/null
+++ b/benchmarks/release-criteria.json
@@ -0,0 +1,26 @@
+{
+ "maximum_latency_ratio": 2.0,
+ "maximum_allocation_ratio": 2.0,
+ "material_latency_regression_ratio": 1.25,
+ "minimum_reference_latency_ns": 1000.0,
+ "reviewed_exceptions": [
+ {
+ "workload": "llsd_json",
+ "maximum_latency_ratio": 2.0,
+ "maximum_allocation_ratio": 2.1,
+ "rationale": "the bounded owned Rust tree is more than four times faster; up to 10% extra allocation bytes are accepted"
+ },
+ {
+ "workload": "rendering",
+ "maximum_latency_ratio": 8.0,
+ "maximum_allocation_ratio": 4.0,
+ "rationale": "Rust produces the complete checked six-face box mesh; the pinned SimpleRenderer is a documented one-face placeholder"
+ },
+ {
+ "workload": "client_throughput",
+ "maximum_latency_ratio": 2.0,
+ "maximum_allocation_ratio": 2.0,
+ "rationale": "Rust returns checked Results and owns the bounded OSD map while allocating fewer bytes; the measured latency remains below the reviewed hard limit"
+ }
+ ]
+}
diff --git a/benchmarks/results/comparison.json b/benchmarks/results/comparison.json
new file mode 100644
index 0000000..eddfd1e
--- /dev/null
+++ b/benchmarks/results/comparison.json
@@ -0,0 +1,194 @@
+{
+ "schema": 1,
+ "reference_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba",
+ "fixture_hashes": {
+ "agent_pause.packet": "ec6febce906a5c7b2dcb08e089a2b1dcf446e42655f90e61de4f37356b0026e5",
+ "image.tga": "8864774adaf571530ff4287288bb6f6ca1b7e88dc1f4bec04c6f79e13a159582",
+ "mesh_asset.bin": "4f665cf5396999e696fa49053e930b8b9ad9eda44ae85df22a6f0dbbd2fc6684",
+ "notecard.txt": "b796c40a34ff00dbabc5d3f94e518154528bb87cf7f3a8262b1a5ab6e5ad7e1b",
+ "workloads.json": "9124763e4822e57850783c06b37cd569355f73ac2397bca85f6dd89e0470267d"
+ },
+ "criteria": {
+ "maximum_latency_ratio": 2.0,
+ "maximum_allocation_ratio": 2.0,
+ "material_latency_regression_ratio": 1.25,
+ "minimum_reference_latency_ns": 1000.0,
+ "reviewed_exceptions": [
+ {
+ "workload": "llsd_json",
+ "maximum_latency_ratio": 2.0,
+ "maximum_allocation_ratio": 2.1,
+ "rationale": "the bounded owned Rust tree is more than four times faster; up to 10% extra allocation bytes are accepted"
+ },
+ {
+ "workload": "rendering",
+ "maximum_latency_ratio": 8.0,
+ "maximum_allocation_ratio": 4.0,
+ "rationale": "Rust produces the complete checked six-face box mesh; the pinned SimpleRenderer is a documented one-face placeholder"
+ },
+ {
+ "workload": "client_throughput",
+ "maximum_latency_ratio": 2.0,
+ "maximum_allocation_ratio": 2.0,
+ "rationale": "Rust returns checked Results and owns the bounded OSD map while allocating fewer bytes; the measured latency remains below the reviewed hard limit"
+ }
+ ]
+ },
+ "results": [
+ {
+ "name": "uuid_math",
+ "rust_latency_ns": 107.41872,
+ "reference_latency_ns": 105.47209,
+ "latency_ratio": 1.0184563518178127,
+ "rust_bytes_per_operation": 36.0,
+ "reference_bytes_per_operation": 40.0,
+ "allocation_ratio": 0.9,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "llsd_xml",
+ "rust_latency_ns": 23361.1135,
+ "reference_latency_ns": 38735.79,
+ "latency_ratio": 0.6030886035885675,
+ "rust_bytes_per_operation": 10938.64,
+ "reference_bytes_per_operation": 28600.0,
+ "allocation_ratio": 0.3824699300699301,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "llsd_json",
+ "rust_latency_ns": 5231.5815,
+ "reference_latency_ns": 21724.418,
+ "latency_ratio": 0.24081572634074708,
+ "rust_bytes_per_operation": 7446.936,
+ "reference_bytes_per_operation": 3680.0,
+ "allocation_ratio": 2.0236239130434783,
+ "accepted": true,
+ "criterion": "reviewed exception: the bounded owned Rust tree is more than four times faster; up to 10% extra allocation bytes are accepted"
+ },
+ {
+ "name": "llsd_binary",
+ "rust_latency_ns": 2688.7605,
+ "reference_latency_ns": 11074.724,
+ "latency_ratio": 0.24278352218980806,
+ "rust_bytes_per_operation": 6749.016,
+ "reference_bytes_per_operation": 7960.0,
+ "allocation_ratio": 0.8478663316582914,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "llsd_notation",
+ "rust_latency_ns": 7007.081,
+ "reference_latency_ns": 18866.287,
+ "latency_ratio": 0.37140752708786845,
+ "rust_bytes_per_operation": 8488.784,
+ "reference_bytes_per_operation": 10096.0,
+ "allocation_ratio": 0.8408066561014262,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "llsd_protobuf",
+ "rust_latency_ns": 7337.0635,
+ "reference_latency_ns": 30965.56,
+ "latency_ratio": 0.23694270344214668,
+ "rust_bytes_per_operation": 8323.672,
+ "reference_bytes_per_operation": 26120.0,
+ "allocation_ratio": 0.31867044410413475,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "packet_codec",
+ "rust_latency_ns": 208.5864,
+ "reference_latency_ns": 175.8286,
+ "latency_ratio": 1.186305299592899,
+ "rust_bytes_per_operation": 124.0,
+ "reference_bytes_per_operation": 264.0,
+ "allocation_ratio": 0.4696969696969697,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "asset_decode",
+ "rust_latency_ns": 288.205,
+ "reference_latency_ns": 2980.13,
+ "latency_ratio": 0.09670886840506956,
+ "rust_bytes_per_operation": 1246.0,
+ "reference_bytes_per_operation": 4512.0,
+ "allocation_ratio": 0.27615248226950356,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "image_decode",
+ "rust_latency_ns": 42671.19,
+ "reference_latency_ns": 48273.63,
+ "latency_ratio": 0.8839440912150175,
+ "rust_bytes_per_operation": 65536.0,
+ "reference_bytes_per_operation": 131612.16,
+ "allocation_ratio": 0.4979479099803544,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "mesh_decode",
+ "rust_latency_ns": 413294.68,
+ "reference_latency_ns": 378537.04,
+ "latency_ratio": 1.0918209747717158,
+ "rust_bytes_per_operation": 507739.92,
+ "reference_bytes_per_operation": 564592.96,
+ "allocation_ratio": 0.8993026055443554,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "inventory_update",
+ "rust_latency_ns": 972.1585,
+ "reference_latency_ns": 757.9809,
+ "latency_ratio": 1.282563320526942,
+ "rust_bytes_per_operation": 373.3421,
+ "reference_bytes_per_operation": 356.5016,
+ "allocation_ratio": 1.0472382171636818,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "object_update",
+ "rust_latency_ns": 27.1764,
+ "reference_latency_ns": 45.77345,
+ "latency_ratio": 0.5937153524586851,
+ "rust_bytes_per_operation": 16.1792,
+ "reference_bytes_per_operation": 10.6552,
+ "allocation_ratio": 1.5184323147383438,
+ "accepted": true,
+ "criterion": "within default release thresholds"
+ },
+ {
+ "name": "rendering",
+ "rust_latency_ns": 5218.82,
+ "reference_latency_ns": 1013.564,
+ "latency_ratio": 5.14897924551385,
+ "rust_bytes_per_operation": 9480.0,
+ "reference_bytes_per_operation": 3048.096,
+ "allocation_ratio": 3.110138263361784,
+ "accepted": true,
+ "criterion": "reviewed exception: Rust produces the complete checked six-face box mesh; the pinned SimpleRenderer is a documented one-face placeholder"
+ },
+ {
+ "name": "client_throughput",
+ "rust_latency_ns": 6231.7982,
+ "reference_latency_ns": 3795.4216,
+ "latency_ratio": 1.6419251552976355,
+ "rust_bytes_per_operation": 11795.3474,
+ "reference_bytes_per_operation": 12053.7952,
+ "allocation_ratio": 0.9785588027910082,
+ "accepted": true,
+ "criterion": "reviewed exception: Rust returns checked Results and owns the bounded OSD map while allocating fewer bytes; the measured latency remains below the reviewed hard limit"
+ }
+ ],
+ "accepted": true
+}
diff --git a/benchmarks/results/csharp-linux-x86_64.json b/benchmarks/results/csharp-linux-x86_64.json
new file mode 100644
index 0000000..561a24d
--- /dev/null
+++ b/benchmarks/results/csharp-linux-x86_64.json
@@ -0,0 +1,1267 @@
+{
+ "schema": 1,
+ "runtime": "dotnet-reference",
+ "reference_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba",
+ "fixture_hashes": {
+ "mesh_asset.bin": "4f665cf5396999e696fa49053e930b8b9ad9eda44ae85df22a6f0dbbd2fc6684",
+ "image.tga": "8864774adaf571530ff4287288bb6f6ca1b7e88dc1f4bec04c6f79e13a159582",
+ "workloads.json": "9124763e4822e57850783c06b37cd569355f73ac2397bca85f6dd89e0470267d",
+ "agent_pause.packet": "ec6febce906a5c7b2dcb08e089a2b1dcf446e42655f90e61de4f37356b0026e5",
+ "notecard.txt": "b796c40a34ff00dbabc5d3f94e518154528bb87cf7f3a8262b1a5ab6e5ad7e1b"
+ },
+ "environment": {
+ "os": "linux",
+ "arch": "x86_64",
+ "logical_cpus": 4,
+ "toolchain": ".NET 8.0.30",
+ "profile": "Release net8.0"
+ },
+ "results": [
+ {
+ "name": "uuid_math",
+ "category": "uuid/math",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 665312,
+ "latency_ns": 665312,
+ "throughput_per_second": 1503.0542061468905,
+ "allocations": null,
+ "bytes_allocated": 40,
+ "retained_bytes": 0
+ },
+ "warm_samples": [
+ {
+ "iterations": 100000,
+ "elapsed_ns": 11108275,
+ "latency_ns": 111.08275,
+ "throughput_per_second": 9002297.836522771,
+ "allocations": null,
+ "bytes_allocated": 4000000,
+ "retained_bytes": 4005568
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 11428448,
+ "latency_ns": 114.28448,
+ "throughput_per_second": 8750094.50102061,
+ "allocations": null,
+ "bytes_allocated": 4000000,
+ "retained_bytes": 4014048
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 10547209,
+ "latency_ns": 105.47209,
+ "throughput_per_second": 9481181.230029669,
+ "allocations": null,
+ "bytes_allocated": 4000000,
+ "retained_bytes": 4014032
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 11064298,
+ "latency_ns": 110.64298,
+ "throughput_per_second": 9038079.053908346,
+ "allocations": null,
+ "bytes_allocated": 4000000,
+ "retained_bytes": -12442600
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 8378733,
+ "latency_ns": 83.78733,
+ "throughput_per_second": 11934978.713368718,
+ "allocations": null,
+ "bytes_allocated": 4000000,
+ "retained_bytes": 4012672
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 7990597,
+ "latency_ns": 79.90597,
+ "throughput_per_second": 12514709.476651119,
+ "allocations": null,
+ "bytes_allocated": 4000000,
+ "retained_bytes": 4013312
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 7917759,
+ "latency_ns": 79.17759,
+ "throughput_per_second": 12629836.295850884,
+ "allocations": null,
+ "bytes_allocated": 4000000,
+ "retained_bytes": 4005040
+ }
+ ],
+ "warm_median": {
+ "iterations": 100000,
+ "elapsed_ns": 10547209,
+ "latency_ns": 105.47209,
+ "throughput_per_second": 9481181.230029669,
+ "allocations": null,
+ "bytes_allocated": 4000000,
+ "retained_bytes": 4014032
+ }
+ },
+ {
+ "name": "llsd_xml",
+ "category": "LLSD",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 24144525,
+ "latency_ns": 24144525,
+ "throughput_per_second": 41.4172571214385,
+ "allocations": null,
+ "bytes_allocated": 40880,
+ "retained_bytes": 41144
+ },
+ "warm_samples": [
+ {
+ "iterations": 2000,
+ "elapsed_ns": 60986807,
+ "latency_ns": 30493.4035,
+ "throughput_per_second": 32793.97788442999,
+ "allocations": null,
+ "bytes_allocated": 57200000,
+ "retained_bytes": 7107784
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 59513215,
+ "latency_ns": 29756.6075,
+ "throughput_per_second": 33605.98146142835,
+ "allocations": null,
+ "bytes_allocated": 57200000,
+ "retained_bytes": 7085888
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 62492465,
+ "latency_ns": 31246.2325,
+ "throughput_per_second": 32003.858385166917,
+ "allocations": null,
+ "bytes_allocated": 57200000,
+ "retained_bytes": -9675416
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 83712603,
+ "latency_ns": 41856.3015,
+ "throughput_per_second": 23891.26521367398,
+ "allocations": null,
+ "bytes_allocated": 57200000,
+ "retained_bytes": 7077608
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 77471580,
+ "latency_ns": 38735.79,
+ "throughput_per_second": 25815.918560070673,
+ "allocations": null,
+ "bytes_allocated": 57200000,
+ "retained_bytes": -9671192
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 107885871,
+ "latency_ns": 53942.9355,
+ "throughput_per_second": 18538.1086648501,
+ "allocations": null,
+ "bytes_allocated": 57200000,
+ "retained_bytes": 7082936
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 103145538,
+ "latency_ns": 51572.769,
+ "throughput_per_second": 19390.077736566753,
+ "allocations": null,
+ "bytes_allocated": 57200000,
+ "retained_bytes": -9679632
+ }
+ ],
+ "warm_median": {
+ "iterations": 2000,
+ "elapsed_ns": 77471580,
+ "latency_ns": 38735.79,
+ "throughput_per_second": 25815.918560070673,
+ "allocations": null,
+ "bytes_allocated": 57200000,
+ "retained_bytes": -9671192
+ }
+ },
+ {
+ "name": "llsd_json",
+ "category": "LLSD",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 10588802,
+ "latency_ns": 10588802,
+ "throughput_per_second": 94.43938983843499,
+ "allocations": null,
+ "bytes_allocated": 10968,
+ "retained_bytes": 8224
+ },
+ "warm_samples": [
+ {
+ "iterations": 2000,
+ "elapsed_ns": 45052652,
+ "latency_ns": 22526.326,
+ "throughput_per_second": 44392.503242650404,
+ "allocations": null,
+ "bytes_allocated": 7360000,
+ "retained_bytes": 7384296
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 43062985,
+ "latency_ns": 21531.4925,
+ "throughput_per_second": 46443.598835519646,
+ "allocations": null,
+ "bytes_allocated": 7360000,
+ "retained_bytes": 7376768
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 42989343,
+ "latency_ns": 21494.6715,
+ "throughput_per_second": 46523.158076642394,
+ "allocations": null,
+ "bytes_allocated": 7360000,
+ "retained_bytes": -9371872
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 43448836,
+ "latency_ns": 21724.418,
+ "throughput_per_second": 46031.15259520416,
+ "allocations": null,
+ "bytes_allocated": 7360000,
+ "retained_bytes": 7384696
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 47440569,
+ "latency_ns": 23720.2845,
+ "throughput_per_second": 42158.01037293629,
+ "allocations": null,
+ "bytes_allocated": 7360000,
+ "retained_bytes": -9393792
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 43516358,
+ "latency_ns": 21758.179,
+ "throughput_per_second": 45959.72852323717,
+ "allocations": null,
+ "bytes_allocated": 7360000,
+ "retained_bytes": 7385112
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 43105547,
+ "latency_ns": 21552.7735,
+ "throughput_per_second": 46397.74087543768,
+ "allocations": null,
+ "bytes_allocated": 7360000,
+ "retained_bytes": -9398248
+ }
+ ],
+ "warm_median": {
+ "iterations": 2000,
+ "elapsed_ns": 43448836,
+ "latency_ns": 21724.418,
+ "throughput_per_second": 46031.15259520416,
+ "allocations": null,
+ "bytes_allocated": 7360000,
+ "retained_bytes": 7384696
+ }
+ },
+ {
+ "name": "llsd_binary",
+ "category": "LLSD",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 2540226,
+ "latency_ns": 2540226,
+ "throughput_per_second": 393.66576044808613,
+ "allocations": null,
+ "bytes_allocated": 8872,
+ "retained_bytes": 8224
+ },
+ "warm_samples": [
+ {
+ "iterations": 2000,
+ "elapsed_ns": 23852474,
+ "latency_ns": 11926.237,
+ "throughput_per_second": 83848.74457886424,
+ "allocations": null,
+ "bytes_allocated": 15920000,
+ "retained_bytes": -804696
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 23342154,
+ "latency_ns": 11671.077,
+ "throughput_per_second": 85681.89550972887,
+ "allocations": null,
+ "bytes_allocated": 15920000,
+ "retained_bytes": -811672
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 22149448,
+ "latency_ns": 11074.724,
+ "throughput_per_second": 90295.70398323245,
+ "allocations": null,
+ "bytes_allocated": 15920000,
+ "retained_bytes": -804384
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 22981111,
+ "latency_ns": 11490.5555,
+ "throughput_per_second": 87027.99442550885,
+ "allocations": null,
+ "bytes_allocated": 15920000,
+ "retained_bytes": -812352
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 21875475,
+ "latency_ns": 10937.7375,
+ "throughput_per_second": 91426.58616555756,
+ "allocations": null,
+ "bytes_allocated": 15920000,
+ "retained_bytes": 15970168
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 21742646,
+ "latency_ns": 10871.323,
+ "throughput_per_second": 91985.12453360092,
+ "allocations": null,
+ "bytes_allocated": 15920000,
+ "retained_bytes": -810952
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 21841744,
+ "latency_ns": 10920.872,
+ "throughput_per_second": 91567.77956925052,
+ "allocations": null,
+ "bytes_allocated": 15920000,
+ "retained_bytes": -801752
+ }
+ ],
+ "warm_median": {
+ "iterations": 2000,
+ "elapsed_ns": 22149448,
+ "latency_ns": 11074.724,
+ "throughput_per_second": 90295.70398323245,
+ "allocations": null,
+ "bytes_allocated": 15920000,
+ "retained_bytes": -804384
+ }
+ },
+ {
+ "name": "llsd_notation",
+ "category": "LLSD",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 2349029,
+ "latency_ns": 2349029,
+ "throughput_per_second": 425.70781373920886,
+ "allocations": null,
+ "bytes_allocated": 10096,
+ "retained_bytes": 8224
+ },
+ "warm_samples": [
+ {
+ "iterations": 2000,
+ "elapsed_ns": 38768835,
+ "latency_ns": 19384.4175,
+ "throughput_per_second": 51587.82821304793,
+ "allocations": null,
+ "bytes_allocated": 20192000,
+ "retained_bytes": 3483136
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 37732574,
+ "latency_ns": 18866.287,
+ "throughput_per_second": 53004.600216248175,
+ "allocations": null,
+ "bytes_allocated": 20192000,
+ "retained_bytes": 3473984
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 37006180,
+ "latency_ns": 18503.09,
+ "throughput_per_second": 54045.02707385631,
+ "allocations": null,
+ "bytes_allocated": 20192000,
+ "retained_bytes": 3482776
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 36928021,
+ "latency_ns": 18464.0105,
+ "throughput_per_second": 54159.41460821852,
+ "allocations": null,
+ "bytes_allocated": 20192000,
+ "retained_bytes": 3474416
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 38526631,
+ "latency_ns": 19263.3155,
+ "throughput_per_second": 51912.14357673787,
+ "allocations": null,
+ "bytes_allocated": 20192000,
+ "retained_bytes": -13289552
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 38605899,
+ "latency_ns": 19302.9495,
+ "throughput_per_second": 51805.55437913776,
+ "allocations": null,
+ "bytes_allocated": 20192000,
+ "retained_bytes": 3472280
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 36768912,
+ "latency_ns": 18384.456,
+ "throughput_per_second": 54393.777003790594,
+ "allocations": null,
+ "bytes_allocated": 20192000,
+ "retained_bytes": 3481152
+ }
+ ],
+ "warm_median": {
+ "iterations": 2000,
+ "elapsed_ns": 37732574,
+ "latency_ns": 18866.287,
+ "throughput_per_second": 53004.600216248175,
+ "allocations": null,
+ "bytes_allocated": 20192000,
+ "retained_bytes": 3473984
+ }
+ },
+ {
+ "name": "llsd_protobuf",
+ "category": "LLSD",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 2338984,
+ "latency_ns": 2338984,
+ "throughput_per_second": 427.5360583911647,
+ "allocations": null,
+ "bytes_allocated": 26248,
+ "retained_bytes": 24672
+ },
+ "warm_samples": [
+ {
+ "iterations": 2000,
+ "elapsed_ns": 61931120,
+ "latency_ns": 30965.56,
+ "throughput_per_second": 32293.94204399985,
+ "allocations": null,
+ "bytes_allocated": 52240000,
+ "retained_bytes": 2076656
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 62118843,
+ "latency_ns": 31059.4215,
+ "throughput_per_second": 32196.349825768648,
+ "allocations": null,
+ "bytes_allocated": 52240000,
+ "retained_bytes": -14697616
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 62671064,
+ "latency_ns": 31335.532,
+ "throughput_per_second": 31912.65429927917,
+ "allocations": null,
+ "bytes_allocated": 52240000,
+ "retained_bytes": 2065528
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 81939101,
+ "latency_ns": 40969.5505,
+ "throughput_per_second": 24408.371285401336,
+ "allocations": null,
+ "bytes_allocated": 52240000,
+ "retained_bytes": 2072856
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 51412333,
+ "latency_ns": 25706.1665,
+ "throughput_per_second": 38901.171825834084,
+ "allocations": null,
+ "bytes_allocated": 52240000,
+ "retained_bytes": 2074512
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 12565310,
+ "latency_ns": 6282.655,
+ "throughput_per_second": 159168.37706351854,
+ "allocations": null,
+ "bytes_allocated": 52240000,
+ "retained_bytes": 2072448
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 12080040,
+ "latency_ns": 6040.02,
+ "throughput_per_second": 165562.36568753084,
+ "allocations": null,
+ "bytes_allocated": 52240000,
+ "retained_bytes": 2075136
+ }
+ ],
+ "warm_median": {
+ "iterations": 2000,
+ "elapsed_ns": 61931120,
+ "latency_ns": 30965.56,
+ "throughput_per_second": 32293.94204399985,
+ "allocations": null,
+ "bytes_allocated": 52240000,
+ "retained_bytes": 2076656
+ }
+ },
+ {
+ "name": "packet_codec",
+ "category": "packet codec",
+ "unit": "operation",
+ "fixture": "agent_pause.packet",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 2983594,
+ "latency_ns": 2983594,
+ "throughput_per_second": 335.166245809584,
+ "allocations": null,
+ "bytes_allocated": 32928,
+ "retained_bytes": 32664
+ },
+ "warm_samples": [
+ {
+ "iterations": 5000,
+ "elapsed_ns": 910933,
+ "latency_ns": 182.1866,
+ "throughput_per_second": 5488877.886738103,
+ "allocations": null,
+ "bytes_allocated": 1320000,
+ "retained_bytes": 1324064
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 2264742,
+ "latency_ns": 452.9484,
+ "throughput_per_second": 2207756.998368909,
+ "allocations": null,
+ "bytes_allocated": 1320000,
+ "retained_bytes": 1324032
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 879143,
+ "latency_ns": 175.8286,
+ "throughput_per_second": 5687356.891882208,
+ "allocations": null,
+ "bytes_allocated": 1320000,
+ "retained_bytes": 1324064
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 781407,
+ "latency_ns": 156.2814,
+ "throughput_per_second": 6398714.114411567,
+ "allocations": null,
+ "bytes_allocated": 1320000,
+ "retained_bytes": 1324064
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 993437,
+ "latency_ns": 198.6874,
+ "throughput_per_second": 5033031.787622164,
+ "allocations": null,
+ "bytes_allocated": 1320000,
+ "retained_bytes": -15450440
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 827617,
+ "latency_ns": 165.5234,
+ "throughput_per_second": 6041441.874683579,
+ "allocations": null,
+ "bytes_allocated": 1320000,
+ "retained_bytes": 1324064
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 825494,
+ "latency_ns": 165.0988,
+ "throughput_per_second": 6056979.214870127,
+ "allocations": null,
+ "bytes_allocated": 1320000,
+ "retained_bytes": 1324064
+ }
+ ],
+ "warm_median": {
+ "iterations": 5000,
+ "elapsed_ns": 879143,
+ "latency_ns": 175.8286,
+ "throughput_per_second": 5687356.891882208,
+ "allocations": null,
+ "bytes_allocated": 1320000,
+ "retained_bytes": 1324064
+ }
+ },
+ {
+ "name": "asset_decode",
+ "category": "asset decode",
+ "unit": "operation",
+ "fixture": "notecard.txt",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 7140988,
+ "latency_ns": 7140988,
+ "throughput_per_second": 140.03664478920845,
+ "allocations": null,
+ "bytes_allocated": 21584,
+ "retained_bytes": 16448
+ },
+ "warm_samples": [
+ {
+ "iterations": 1000,
+ "elapsed_ns": 2751404,
+ "latency_ns": 2751.404,
+ "throughput_per_second": 363450.8054796751,
+ "allocations": null,
+ "bytes_allocated": 4512000,
+ "retained_bytes": 4530776
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 2980130,
+ "latency_ns": 2980.13,
+ "throughput_per_second": 335555.831457017,
+ "allocations": null,
+ "bytes_allocated": 4512000,
+ "retained_bytes": 4523024
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 3177376,
+ "latency_ns": 3177.376,
+ "throughput_per_second": 314725.10650297604,
+ "allocations": null,
+ "bytes_allocated": 4512000,
+ "retained_bytes": -12241168
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 2894190,
+ "latency_ns": 2894.19,
+ "throughput_per_second": 345519.81728912063,
+ "allocations": null,
+ "bytes_allocated": 4512000,
+ "retained_bytes": 4530584
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 3221693,
+ "latency_ns": 3221.693,
+ "throughput_per_second": 310395.80742175,
+ "allocations": null,
+ "bytes_allocated": 4512000,
+ "retained_bytes": 4523088
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 2883543,
+ "latency_ns": 2883.543,
+ "throughput_per_second": 346795.5913957239,
+ "allocations": null,
+ "bytes_allocated": 4512000,
+ "retained_bytes": 4523168
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 3061752,
+ "latency_ns": 3061.752,
+ "throughput_per_second": 326610.38516509504,
+ "allocations": null,
+ "bytes_allocated": 4512000,
+ "retained_bytes": -12250312
+ }
+ ],
+ "warm_median": {
+ "iterations": 1000,
+ "elapsed_ns": 2980130,
+ "latency_ns": 2980.13,
+ "throughput_per_second": 335555.831457017,
+ "allocations": null,
+ "bytes_allocated": 4512000,
+ "retained_bytes": 4523024
+ }
+ },
+ {
+ "name": "image_decode",
+ "category": "image decode",
+ "unit": "operation",
+ "fixture": "image.tga",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 5722160,
+ "latency_ns": 5722160,
+ "throughput_per_second": 174.75918184741428,
+ "allocations": null,
+ "bytes_allocated": 132392,
+ "retained_bytes": 131312
+ },
+ "warm_samples": [
+ {
+ "iterations": 100,
+ "elapsed_ns": 4780382,
+ "latency_ns": 47803.82,
+ "throughput_per_second": 20918.830336153052,
+ "allocations": null,
+ "bytes_allocated": 13160800,
+ "retained_bytes": 13172616
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4827363,
+ "latency_ns": 48273.63,
+ "throughput_per_second": 20715.243498365464,
+ "allocations": null,
+ "bytes_allocated": 13161216,
+ "retained_bytes": -3451024
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4902175,
+ "latency_ns": 49021.75,
+ "throughput_per_second": 20399.108558955973,
+ "allocations": null,
+ "bytes_allocated": 13161216,
+ "retained_bytes": -3361160
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4637335,
+ "latency_ns": 46373.35,
+ "throughput_per_second": 21564.109558615022,
+ "allocations": null,
+ "bytes_allocated": 13161216,
+ "retained_bytes": -3493064
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4657236,
+ "latency_ns": 46572.36,
+ "throughput_per_second": 21471.96319877283,
+ "allocations": null,
+ "bytes_allocated": 13161216,
+ "retained_bytes": -3558608
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4903457,
+ "latency_ns": 49034.57,
+ "throughput_per_second": 20393.77524876837,
+ "allocations": null,
+ "bytes_allocated": 13160800,
+ "retained_bytes": 13179208
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4844208,
+ "latency_ns": 48442.08,
+ "throughput_per_second": 20643.209374989678,
+ "allocations": null,
+ "bytes_allocated": 13161216,
+ "retained_bytes": -3689912
+ }
+ ],
+ "warm_median": {
+ "iterations": 100,
+ "elapsed_ns": 4827363,
+ "latency_ns": 48273.63,
+ "throughput_per_second": 20715.243498365464,
+ "allocations": null,
+ "bytes_allocated": 13161216,
+ "retained_bytes": -3451024
+ }
+ },
+ {
+ "name": "mesh_decode",
+ "category": "mesh decode",
+ "unit": "operation",
+ "fixture": "mesh_asset.bin",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 9096173,
+ "latency_ns": 9096173,
+ "throughput_per_second": 109.93634355898902,
+ "allocations": null,
+ "bytes_allocated": 573232,
+ "retained_bytes": 575920
+ },
+ "warm_samples": [
+ {
+ "iterations": 25,
+ "elapsed_ns": 16966110,
+ "latency_ns": 678644.4,
+ "throughput_per_second": 1473.5257522201614,
+ "allocations": null,
+ "bytes_allocated": 14114824,
+ "retained_bytes": -12259824
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 9802867,
+ "latency_ns": 392114.68,
+ "throughput_per_second": 2550.274322807807,
+ "allocations": null,
+ "bytes_allocated": 14114824,
+ "retained_bytes": 565896
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 9849519,
+ "latency_ns": 393980.76,
+ "throughput_per_second": 2538.195012365579,
+ "allocations": null,
+ "bytes_allocated": 14114824,
+ "retained_bytes": 566200
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 9463426,
+ "latency_ns": 378537.04,
+ "throughput_per_second": 2641.749404496849,
+ "allocations": null,
+ "bytes_allocated": 14114824,
+ "retained_bytes": 566200
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 9178127,
+ "latency_ns": 367125.08,
+ "throughput_per_second": 2723.8672988508442,
+ "allocations": null,
+ "bytes_allocated": 14114824,
+ "retained_bytes": 566200
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 9043023,
+ "latency_ns": 361720.92,
+ "throughput_per_second": 2764.562248708203,
+ "allocations": null,
+ "bytes_allocated": 14114824,
+ "retained_bytes": 566232
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 9250566,
+ "latency_ns": 370022.64,
+ "throughput_per_second": 2702.5373366343206,
+ "allocations": null,
+ "bytes_allocated": 14114824,
+ "retained_bytes": 557976
+ }
+ ],
+ "warm_median": {
+ "iterations": 25,
+ "elapsed_ns": 9463426,
+ "latency_ns": 378537.04,
+ "throughput_per_second": 2641.749404496849,
+ "allocations": null,
+ "bytes_allocated": 14114824,
+ "retained_bytes": 566200
+ }
+ },
+ {
+ "name": "inventory_update",
+ "category": "inventory update",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 34317809,
+ "latency_ns": 34317809,
+ "throughput_per_second": 29.139389405658154,
+ "allocations": null,
+ "bytes_allocated": 152664,
+ "retained_bytes": 156160
+ },
+ "warm_samples": [
+ {
+ "iterations": 10000,
+ "elapsed_ns": 8503752,
+ "latency_ns": 850.3752,
+ "throughput_per_second": 1175951.5094043193,
+ "allocations": null,
+ "bytes_allocated": 3565016,
+ "retained_bytes": 3569216
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 7778828,
+ "latency_ns": 777.8828,
+ "throughput_per_second": 1285540.7009899179,
+ "allocations": null,
+ "bytes_allocated": 3565016,
+ "retained_bytes": 3577392
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 7579809,
+ "latency_ns": 757.9809,
+ "throughput_per_second": 1319294.4571558465,
+ "allocations": null,
+ "bytes_allocated": 3565016,
+ "retained_bytes": 3577368
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 8533034,
+ "latency_ns": 853.3034,
+ "throughput_per_second": 1171916.1086197477,
+ "allocations": null,
+ "bytes_allocated": 3565016,
+ "retained_bytes": -12640272
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 7261489,
+ "latency_ns": 726.1489,
+ "throughput_per_second": 1377128.02429364,
+ "allocations": null,
+ "bytes_allocated": 3565272,
+ "retained_bytes": 3576744
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 7321690,
+ "latency_ns": 732.169,
+ "throughput_per_second": 1365804.8893083427,
+ "allocations": null,
+ "bytes_allocated": 3565016,
+ "retained_bytes": 3577384
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 7088339,
+ "latency_ns": 708.8339,
+ "throughput_per_second": 1410767.7412155373,
+ "allocations": null,
+ "bytes_allocated": 3565016,
+ "retained_bytes": 3577400
+ }
+ ],
+ "warm_median": {
+ "iterations": 10000,
+ "elapsed_ns": 7579809,
+ "latency_ns": 757.9809,
+ "throughput_per_second": 1319294.4571558465,
+ "allocations": null,
+ "bytes_allocated": 3565016,
+ "retained_bytes": 3577368
+ }
+ },
+ {
+ "name": "object_update",
+ "category": "object update",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 980337,
+ "latency_ns": 980337,
+ "throughput_per_second": 1020.057388428673,
+ "allocations": null,
+ "bytes_allocated": 213168,
+ "retained_bytes": 213824
+ },
+ "warm_samples": [
+ {
+ "iterations": 20000,
+ "elapsed_ns": 1948776,
+ "latency_ns": 97.4388,
+ "throughput_per_second": 10262852.169772206,
+ "allocations": null,
+ "bytes_allocated": 213104,
+ "retained_bytes": 213824
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 917993,
+ "latency_ns": 45.89965,
+ "throughput_per_second": 21786658.503931947,
+ "allocations": null,
+ "bytes_allocated": 213104,
+ "retained_bytes": 213824
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 899585,
+ "latency_ns": 44.97925,
+ "throughput_per_second": 22232473.862947915,
+ "allocations": null,
+ "bytes_allocated": 213104,
+ "retained_bytes": 213824
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 926005,
+ "latency_ns": 46.30025,
+ "throughput_per_second": 21598155.517518803,
+ "allocations": null,
+ "bytes_allocated": 213104,
+ "retained_bytes": 213824
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 915469,
+ "latency_ns": 45.77345,
+ "throughput_per_second": 21846725.558156528,
+ "allocations": null,
+ "bytes_allocated": 213104,
+ "retained_bytes": 213824
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 911142,
+ "latency_ns": 45.5571,
+ "throughput_per_second": 21950475.337543435,
+ "allocations": null,
+ "bytes_allocated": 213104,
+ "retained_bytes": 213824
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 906956,
+ "latency_ns": 45.3478,
+ "throughput_per_second": 22051786.415217496,
+ "allocations": null,
+ "bytes_allocated": 213104,
+ "retained_bytes": 213824
+ }
+ ],
+ "warm_median": {
+ "iterations": 20000,
+ "elapsed_ns": 915469,
+ "latency_ns": 45.77345,
+ "throughput_per_second": 21846725.558156528,
+ "allocations": null,
+ "bytes_allocated": 213104,
+ "retained_bytes": 213824
+ }
+ },
+ {
+ "name": "rendering",
+ "category": "rendering",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 1273057,
+ "latency_ns": 1273057,
+ "throughput_per_second": 785.5107823137535,
+ "allocations": null,
+ "bytes_allocated": 3136,
+ "retained_bytes": 0
+ },
+ "warm_samples": [
+ {
+ "iterations": 250,
+ "elapsed_ns": 280963,
+ "latency_ns": 1123.852,
+ "throughput_per_second": 889796.8771688798,
+ "allocations": null,
+ "bytes_allocated": 762024,
+ "retained_bytes": 764832
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 257508,
+ "latency_ns": 1030.032,
+ "throughput_per_second": 970843.6242757507,
+ "allocations": null,
+ "bytes_allocated": 762024,
+ "retained_bytes": 764832
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 1135100,
+ "latency_ns": 4540.4,
+ "throughput_per_second": 220244.91234252488,
+ "allocations": null,
+ "bytes_allocated": 762024,
+ "retained_bytes": -16398136
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 240994,
+ "latency_ns": 963.976,
+ "throughput_per_second": 1037370.2249848545,
+ "allocations": null,
+ "bytes_allocated": 762024,
+ "retained_bytes": 756608
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 247724,
+ "latency_ns": 990.896,
+ "throughput_per_second": 1009187.6443138331,
+ "allocations": null,
+ "bytes_allocated": 762024,
+ "retained_bytes": 764832
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 236606,
+ "latency_ns": 946.424,
+ "throughput_per_second": 1056608.8772051428,
+ "allocations": null,
+ "bytes_allocated": 762024,
+ "retained_bytes": 764832
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 253391,
+ "latency_ns": 1013.564,
+ "throughput_per_second": 986617.5199592725,
+ "allocations": null,
+ "bytes_allocated": 762024,
+ "retained_bytes": 764832
+ }
+ ],
+ "warm_median": {
+ "iterations": 250,
+ "elapsed_ns": 253391,
+ "latency_ns": 1013.564,
+ "throughput_per_second": 986617.5199592725,
+ "allocations": null,
+ "bytes_allocated": 762024,
+ "retained_bytes": 764832
+ }
+ },
+ {
+ "name": "client_throughput",
+ "category": "client throughput",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 513012,
+ "latency_ns": 513012,
+ "throughput_per_second": 1949.2721417822586,
+ "allocations": null,
+ "bytes_allocated": 121008,
+ "retained_bytes": 123360
+ },
+ "warm_samples": [
+ {
+ "iterations": 5000,
+ "elapsed_ns": 20926196,
+ "latency_ns": 4185.2392,
+ "throughput_per_second": 238934.9693561123,
+ "allocations": null,
+ "bytes_allocated": 60268720,
+ "retained_bytes": -6796288
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 19191492,
+ "latency_ns": 3838.2984,
+ "throughput_per_second": 260532.11496010836,
+ "allocations": null,
+ "bytes_allocated": 60268976,
+ "retained_bytes": 10188712
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 18533991,
+ "latency_ns": 3706.7982,
+ "throughput_per_second": 269774.5995452356,
+ "allocations": null,
+ "bytes_allocated": 60268976,
+ "retained_bytes": -6587608
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 18430355,
+ "latency_ns": 3686.071,
+ "throughput_per_second": 271291.57305977016,
+ "allocations": null,
+ "bytes_allocated": 60268976,
+ "retained_bytes": 10181016
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 18977108,
+ "latency_ns": 3795.4216,
+ "throughput_per_second": 263475.34092128265,
+ "allocations": null,
+ "bytes_allocated": 60268976,
+ "retained_bytes": -6589280
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 18185807,
+ "latency_ns": 3637.1614,
+ "throughput_per_second": 274939.682357786,
+ "allocations": null,
+ "bytes_allocated": 60268976,
+ "retained_bytes": -6586920
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 19801070,
+ "latency_ns": 3960.214,
+ "throughput_per_second": 252511.60669600178,
+ "allocations": null,
+ "bytes_allocated": 60268976,
+ "retained_bytes": 10188608
+ }
+ ],
+ "warm_median": {
+ "iterations": 5000,
+ "elapsed_ns": 18977108,
+ "latency_ns": 3795.4216,
+ "throughput_per_second": 263475.34092128265,
+ "allocations": null,
+ "bytes_allocated": 60268976,
+ "retained_bytes": -6589280
+ }
+ }
+ ]
+}
diff --git a/benchmarks/results/rust-linux-x86_64.json b/benchmarks/results/rust-linux-x86_64.json
new file mode 100644
index 0000000..078c67b
--- /dev/null
+++ b/benchmarks/results/rust-linux-x86_64.json
@@ -0,0 +1,1267 @@
+{
+ "schema": 1,
+ "runtime": "rust-native",
+ "reference_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba",
+ "fixture_hashes": {
+ "workloads.json": "9124763e4822e57850783c06b37cd569355f73ac2397bca85f6dd89e0470267d",
+ "notecard.txt": "b796c40a34ff00dbabc5d3f94e518154528bb87cf7f3a8262b1a5ab6e5ad7e1b",
+ "agent_pause.packet": "ec6febce906a5c7b2dcb08e089a2b1dcf446e42655f90e61de4f37356b0026e5",
+ "mesh_asset.bin": "4f665cf5396999e696fa49053e930b8b9ad9eda44ae85df22a6f0dbbd2fc6684",
+ "image.tga": "8864774adaf571530ff4287288bb6f6ca1b7e88dc1f4bec04c6f79e13a159582"
+ },
+ "environment": {
+ "os": "linux",
+ "arch": "x86_64",
+ "logical_cpus": 4,
+ "toolchain": "rustc 1.97.1 (8bab26f4f 2026-07-14)",
+ "profile": "benchmark (opt-level=1, debug=0, incremental=false)"
+ },
+ "results": [
+ {
+ "name": "uuid_math",
+ "category": "uuid/math",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 14532,
+ "latency_ns": 14532.0,
+ "throughput_per_second": 68813.65262868152,
+ "allocations": 1,
+ "bytes_allocated": 36,
+ "retained_bytes": 0
+ },
+ "warm_samples": [
+ {
+ "iterations": 100000,
+ "elapsed_ns": 10976966,
+ "latency_ns": 109.76966,
+ "throughput_per_second": 9109985.400337398,
+ "allocations": 100000,
+ "bytes_allocated": 3600000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 10741872,
+ "latency_ns": 107.41872,
+ "throughput_per_second": 9309364.3268138,
+ "allocations": 100000,
+ "bytes_allocated": 3600000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 10742173,
+ "latency_ns": 107.42173,
+ "throughput_per_second": 9309103.474688035,
+ "allocations": 100000,
+ "bytes_allocated": 3600000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 10670957,
+ "latency_ns": 106.70957,
+ "throughput_per_second": 9371230.715295732,
+ "allocations": 100000,
+ "bytes_allocated": 3600000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 10859259,
+ "latency_ns": 108.59259,
+ "throughput_per_second": 9208731.46132715,
+ "allocations": 100000,
+ "bytes_allocated": 3600000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 10525647,
+ "latency_ns": 105.25647,
+ "throughput_per_second": 9500603.62085105,
+ "allocations": 100000,
+ "bytes_allocated": 3600000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100000,
+ "elapsed_ns": 10432807,
+ "latency_ns": 104.32807,
+ "throughput_per_second": 9585148.081431966,
+ "allocations": 100000,
+ "bytes_allocated": 3600000,
+ "retained_bytes": 0
+ }
+ ],
+ "warm_median": {
+ "iterations": 100000,
+ "elapsed_ns": 10741872,
+ "latency_ns": 107.41872,
+ "throughput_per_second": 9309364.3268138,
+ "allocations": 100000,
+ "bytes_allocated": 3600000,
+ "retained_bytes": 0
+ }
+ },
+ {
+ "name": "llsd_xml",
+ "category": "LLSD",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 111108,
+ "latency_ns": 111108.0,
+ "throughput_per_second": 9000.252007056199,
+ "allocations": 423,
+ "bytes_allocated": 10922,
+ "retained_bytes": 4180
+ },
+ "warm_samples": [
+ {
+ "iterations": 2000,
+ "elapsed_ns": 46185538,
+ "latency_ns": 23092.769,
+ "throughput_per_second": 43303.59862864432,
+ "allocations": 846000,
+ "bytes_allocated": 21875552,
+ "retained_bytes": 8391552
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 46722227,
+ "latency_ns": 23361.1135,
+ "throughput_per_second": 42806.17873801264,
+ "allocations": 846000,
+ "bytes_allocated": 21877280,
+ "retained_bytes": 8393280
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 54708409,
+ "latency_ns": 27354.2045,
+ "throughput_per_second": 36557.45134171239,
+ "allocations": 846000,
+ "bytes_allocated": 21877808,
+ "retained_bytes": 8393808
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 48713647,
+ "latency_ns": 24356.8235,
+ "throughput_per_second": 41056.25678159552,
+ "allocations": 846000,
+ "bytes_allocated": 21876288,
+ "retained_bytes": 8392288
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 46167661,
+ "latency_ns": 23083.8305,
+ "throughput_per_second": 43320.36660899932,
+ "allocations": 846000,
+ "bytes_allocated": 21876048,
+ "retained_bytes": 8392048
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 45971997,
+ "latency_ns": 22985.9985,
+ "throughput_per_second": 43504.74485587389,
+ "allocations": 846000,
+ "bytes_allocated": 21876752,
+ "retained_bytes": 8392752
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 48296739,
+ "latency_ns": 24148.3695,
+ "throughput_per_second": 41410.66335762338,
+ "allocations": 846000,
+ "bytes_allocated": 21877824,
+ "retained_bytes": 8393824
+ }
+ ],
+ "warm_median": {
+ "iterations": 2000,
+ "elapsed_ns": 46722227,
+ "latency_ns": 23361.1135,
+ "throughput_per_second": 42806.17873801264,
+ "allocations": 846000,
+ "bytes_allocated": 21877280,
+ "retained_bytes": 8393280
+ }
+ },
+ {
+ "name": "llsd_json",
+ "category": "LLSD",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 16675,
+ "latency_ns": 16675.0,
+ "throughput_per_second": 59970.014992503755,
+ "allocations": 66,
+ "bytes_allocated": 7431,
+ "retained_bytes": 2768
+ },
+ "warm_samples": [
+ {
+ "iterations": 2000,
+ "elapsed_ns": 10575903,
+ "latency_ns": 5287.9515,
+ "throughput_per_second": 189109.14746476023,
+ "allocations": 132000,
+ "bytes_allocated": 14894880,
+ "retained_bytes": 5568880
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 10391805,
+ "latency_ns": 5195.9025,
+ "throughput_per_second": 192459.34657164948,
+ "allocations": 132000,
+ "bytes_allocated": 14896016,
+ "retained_bytes": 5570016
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 10506537,
+ "latency_ns": 5253.2685,
+ "throughput_per_second": 190357.67922389653,
+ "allocations": 132000,
+ "bytes_allocated": 14895680,
+ "retained_bytes": 5569680
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 10276912,
+ "latency_ns": 5138.456,
+ "throughput_per_second": 194610.98820346035,
+ "allocations": 132000,
+ "bytes_allocated": 14893840,
+ "retained_bytes": 5567840
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 10406939,
+ "latency_ns": 5203.4695,
+ "throughput_per_second": 192179.46794922117,
+ "allocations": 132000,
+ "bytes_allocated": 14895024,
+ "retained_bytes": 5569024
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 10463163,
+ "latency_ns": 5231.5815,
+ "throughput_per_second": 191146.78802193946,
+ "allocations": 132000,
+ "bytes_allocated": 14893872,
+ "retained_bytes": 5567872
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 12578610,
+ "latency_ns": 6289.305,
+ "throughput_per_second": 159000.08029504053,
+ "allocations": 132000,
+ "bytes_allocated": 14895744,
+ "retained_bytes": 5569744
+ }
+ ],
+ "warm_median": {
+ "iterations": 2000,
+ "elapsed_ns": 10463163,
+ "latency_ns": 5231.5815,
+ "throughput_per_second": 191146.78802193946,
+ "allocations": 132000,
+ "bytes_allocated": 14893872,
+ "retained_bytes": 5567872
+ }
+ },
+ {
+ "name": "llsd_binary",
+ "category": "LLSD",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 24336,
+ "latency_ns": 24336.0,
+ "throughput_per_second": 41091.3872452334,
+ "allocations": 28,
+ "bytes_allocated": 6734,
+ "retained_bytes": 1456
+ },
+ "warm_samples": [
+ {
+ "iterations": 2000,
+ "elapsed_ns": 5359845,
+ "latency_ns": 2679.9225,
+ "throughput_per_second": 373145.11893534235,
+ "allocations": 56000,
+ "bytes_allocated": 13499248,
+ "retained_bytes": 2943248
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 5446085,
+ "latency_ns": 2723.0425,
+ "throughput_per_second": 367236.2807411195,
+ "allocations": 56000,
+ "bytes_allocated": 13497408,
+ "retained_bytes": 2941408
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 5377521,
+ "latency_ns": 2688.7605,
+ "throughput_per_second": 371918.58479027794,
+ "allocations": 56000,
+ "bytes_allocated": 13498032,
+ "retained_bytes": 2942032
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 5806547,
+ "latency_ns": 2903.2735,
+ "throughput_per_second": 344438.78608060867,
+ "allocations": 56000,
+ "bytes_allocated": 13499536,
+ "retained_bytes": 2943536
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 5274505,
+ "latency_ns": 2637.2525,
+ "throughput_per_second": 379182.50148592144,
+ "allocations": 56000,
+ "bytes_allocated": 13499360,
+ "retained_bytes": 2943360
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 5293314,
+ "latency_ns": 2646.657,
+ "throughput_per_second": 377835.13315099006,
+ "allocations": 56000,
+ "bytes_allocated": 13499056,
+ "retained_bytes": 2943056
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 5610312,
+ "latency_ns": 2805.156,
+ "throughput_per_second": 356486.4128768596,
+ "allocations": 56000,
+ "bytes_allocated": 13500112,
+ "retained_bytes": 2944112
+ }
+ ],
+ "warm_median": {
+ "iterations": 2000,
+ "elapsed_ns": 5377521,
+ "latency_ns": 2688.7605,
+ "throughput_per_second": 371918.58479027794,
+ "allocations": 56000,
+ "bytes_allocated": 13498032,
+ "retained_bytes": 2942032
+ }
+ },
+ {
+ "name": "llsd_notation",
+ "category": "LLSD",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 21763,
+ "latency_ns": 21763.0,
+ "throughput_per_second": 45949.547396958136,
+ "allocations": 117,
+ "bytes_allocated": 8520,
+ "retained_bytes": 3406
+ },
+ "warm_samples": [
+ {
+ "iterations": 2000,
+ "elapsed_ns": 13988954,
+ "latency_ns": 6994.477,
+ "throughput_per_second": 142969.94614465098,
+ "allocations": 234000,
+ "bytes_allocated": 16977248,
+ "retained_bytes": 6749248
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 14992545,
+ "latency_ns": 7496.2725,
+ "throughput_per_second": 133399.63295090993,
+ "allocations": 234000,
+ "bytes_allocated": 16976992,
+ "retained_bytes": 6748992
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 14936402,
+ "latency_ns": 7468.201,
+ "throughput_per_second": 133901.05595711738,
+ "allocations": 234000,
+ "bytes_allocated": 16976704,
+ "retained_bytes": 6748704
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 14490209,
+ "latency_ns": 7245.1045,
+ "throughput_per_second": 138024.23415700905,
+ "allocations": 234000,
+ "bytes_allocated": 16975632,
+ "retained_bytes": 6747632
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 14014162,
+ "latency_ns": 7007.081,
+ "throughput_per_second": 142712.77868773032,
+ "allocations": 234000,
+ "bytes_allocated": 16977568,
+ "retained_bytes": 6749568
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 14006721,
+ "latency_ns": 7003.3605,
+ "throughput_per_second": 142788.59413277384,
+ "allocations": 234000,
+ "bytes_allocated": 16977152,
+ "retained_bytes": 6749152
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 13877978,
+ "latency_ns": 6938.989,
+ "throughput_per_second": 144113.2130343484,
+ "allocations": 234000,
+ "bytes_allocated": 16978080,
+ "retained_bytes": 6750080
+ }
+ ],
+ "warm_median": {
+ "iterations": 2000,
+ "elapsed_ns": 14014162,
+ "latency_ns": 7007.081,
+ "throughput_per_second": 142712.77868773032,
+ "allocations": 234000,
+ "bytes_allocated": 16977568,
+ "retained_bytes": 6749568
+ }
+ },
+ {
+ "name": "llsd_protobuf",
+ "category": "LLSD",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 16014,
+ "latency_ns": 16014.0,
+ "throughput_per_second": 62445.36030972899,
+ "allocations": 96,
+ "bytes_allocated": 8340,
+ "retained_bytes": 4055
+ },
+ "warm_samples": [
+ {
+ "iterations": 2000,
+ "elapsed_ns": 14682190,
+ "latency_ns": 7341.095,
+ "throughput_per_second": 136219.46044833912,
+ "allocations": 192000,
+ "bytes_allocated": 16648688,
+ "retained_bytes": 8078688
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 22046553,
+ "latency_ns": 11023.2765,
+ "throughput_per_second": 90717.1293399018,
+ "allocations": 192000,
+ "bytes_allocated": 16647488,
+ "retained_bytes": 8077488
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 20776700,
+ "latency_ns": 10388.35,
+ "throughput_per_second": 96261.67774478142,
+ "allocations": 192000,
+ "bytes_allocated": 16648960,
+ "retained_bytes": 8078960
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 14334785,
+ "latency_ns": 7167.3925,
+ "throughput_per_second": 139520.75318883403,
+ "allocations": 192000,
+ "bytes_allocated": 16647056,
+ "retained_bytes": 8077056
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 14674127,
+ "latency_ns": 7337.0635,
+ "throughput_per_second": 136294.30902431198,
+ "allocations": 192000,
+ "bytes_allocated": 16647344,
+ "retained_bytes": 8077344
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 14009685,
+ "latency_ns": 7004.8425,
+ "throughput_per_second": 142758.38464605022,
+ "allocations": 192000,
+ "bytes_allocated": 16649776,
+ "retained_bytes": 8079776
+ },
+ {
+ "iterations": 2000,
+ "elapsed_ns": 14140953,
+ "latency_ns": 7070.4765,
+ "throughput_per_second": 141433.18346366048,
+ "allocations": 192000,
+ "bytes_allocated": 16648672,
+ "retained_bytes": 8078672
+ }
+ ],
+ "warm_median": {
+ "iterations": 2000,
+ "elapsed_ns": 14674127,
+ "latency_ns": 7337.0635,
+ "throughput_per_second": 136294.30902431198,
+ "allocations": 192000,
+ "bytes_allocated": 16647344,
+ "retained_bytes": 8077344
+ }
+ },
+ {
+ "name": "packet_codec",
+ "category": "packet codec",
+ "unit": "operation",
+ "fixture": "agent_pause.packet",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 20671,
+ "latency_ns": 20671.0,
+ "throughput_per_second": 48376.95321948624,
+ "allocations": 4,
+ "bytes_allocated": 124,
+ "retained_bytes": 0
+ },
+ "warm_samples": [
+ {
+ "iterations": 5000,
+ "elapsed_ns": 1033638,
+ "latency_ns": 206.7276,
+ "throughput_per_second": 4837283.459005958,
+ "allocations": 20000,
+ "bytes_allocated": 620000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 1111714,
+ "latency_ns": 222.3428,
+ "throughput_per_second": 4497559.624147938,
+ "allocations": 20000,
+ "bytes_allocated": 620000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 1042932,
+ "latency_ns": 208.5864,
+ "throughput_per_second": 4794176.4180215,
+ "allocations": 20000,
+ "bytes_allocated": 620000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 1030591,
+ "latency_ns": 206.1182,
+ "throughput_per_second": 4851585.15841881,
+ "allocations": 20000,
+ "bytes_allocated": 620000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 1024753,
+ "latency_ns": 204.9506,
+ "throughput_per_second": 4879224.554599986,
+ "allocations": 20000,
+ "bytes_allocated": 620000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 1088531,
+ "latency_ns": 217.7062,
+ "throughput_per_second": 4593346.445806321,
+ "allocations": 20000,
+ "bytes_allocated": 620000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 1089621,
+ "latency_ns": 217.9242,
+ "throughput_per_second": 4588751.501668929,
+ "allocations": 20000,
+ "bytes_allocated": 620000,
+ "retained_bytes": 0
+ }
+ ],
+ "warm_median": {
+ "iterations": 5000,
+ "elapsed_ns": 1042932,
+ "latency_ns": 208.5864,
+ "throughput_per_second": 4794176.4180215,
+ "allocations": 20000,
+ "bytes_allocated": 620000,
+ "retained_bytes": 0
+ }
+ },
+ {
+ "name": "asset_decode",
+ "category": "asset decode",
+ "unit": "operation",
+ "fixture": "notecard.txt",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 15524,
+ "latency_ns": 15524.0,
+ "throughput_per_second": 64416.387528987376,
+ "allocations": 8,
+ "bytes_allocated": 1246,
+ "retained_bytes": 0
+ },
+ "warm_samples": [
+ {
+ "iterations": 1000,
+ "elapsed_ns": 287813,
+ "latency_ns": 287.813,
+ "throughput_per_second": 3474478.2202332765,
+ "allocations": 8000,
+ "bytes_allocated": 1246000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 275865,
+ "latency_ns": 275.865,
+ "throughput_per_second": 3624961.4847842245,
+ "allocations": 8000,
+ "bytes_allocated": 1246000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 290298,
+ "latency_ns": 290.298,
+ "throughput_per_second": 3444736.098767474,
+ "allocations": 8000,
+ "bytes_allocated": 1246000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 293793,
+ "latency_ns": 293.793,
+ "throughput_per_second": 3403757.0670506107,
+ "allocations": 8000,
+ "bytes_allocated": 1246000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 284408,
+ "latency_ns": 284.408,
+ "throughput_per_second": 3516075.4971730756,
+ "allocations": 8000,
+ "bytes_allocated": 1246000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 288205,
+ "latency_ns": 288.205,
+ "throughput_per_second": 3469752.433163894,
+ "allocations": 8000,
+ "bytes_allocated": 1246000,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 1000,
+ "elapsed_ns": 356367,
+ "latency_ns": 356.367,
+ "throughput_per_second": 2806095.962869738,
+ "allocations": 8000,
+ "bytes_allocated": 1246000,
+ "retained_bytes": 0
+ }
+ ],
+ "warm_median": {
+ "iterations": 1000,
+ "elapsed_ns": 288205,
+ "latency_ns": 288.205,
+ "throughput_per_second": 3469752.433163894,
+ "allocations": 8000,
+ "bytes_allocated": 1246000,
+ "retained_bytes": 0
+ }
+ },
+ {
+ "name": "image_decode",
+ "category": "image decode",
+ "unit": "operation",
+ "fixture": "image.tga",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 92169,
+ "latency_ns": 92169.0,
+ "throughput_per_second": 10849.634909785285,
+ "allocations": 4,
+ "bytes_allocated": 65536,
+ "retained_bytes": 0
+ },
+ "warm_samples": [
+ {
+ "iterations": 100,
+ "elapsed_ns": 4240429,
+ "latency_ns": 42404.29,
+ "throughput_per_second": 23582.519598842475,
+ "allocations": 400,
+ "bytes_allocated": 6553600,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4267119,
+ "latency_ns": 42671.19,
+ "throughput_per_second": 23435.015522182533,
+ "allocations": 400,
+ "bytes_allocated": 6553600,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4215300,
+ "latency_ns": 42153.0,
+ "throughput_per_second": 23723.10393091832,
+ "allocations": 400,
+ "bytes_allocated": 6553600,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 5604333,
+ "latency_ns": 56043.33,
+ "throughput_per_second": 17843.336575467587,
+ "allocations": 400,
+ "bytes_allocated": 6553600,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4531937,
+ "latency_ns": 45319.37,
+ "throughput_per_second": 22065.620064886163,
+ "allocations": 400,
+ "bytes_allocated": 6553600,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4158375,
+ "latency_ns": 41583.75,
+ "throughput_per_second": 24047.855231911504,
+ "allocations": 400,
+ "bytes_allocated": 6553600,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 100,
+ "elapsed_ns": 4803927,
+ "latency_ns": 48039.27,
+ "throughput_per_second": 20816.302995445185,
+ "allocations": 400,
+ "bytes_allocated": 6553600,
+ "retained_bytes": 0
+ }
+ ],
+ "warm_median": {
+ "iterations": 100,
+ "elapsed_ns": 4267119,
+ "latency_ns": 42671.19,
+ "throughput_per_second": 23435.015522182533,
+ "allocations": 400,
+ "bytes_allocated": 6553600,
+ "retained_bytes": 0
+ }
+ },
+ {
+ "name": "mesh_decode",
+ "category": "mesh decode",
+ "unit": "operation",
+ "fixture": "mesh_asset.bin",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 702648,
+ "latency_ns": 702648.0,
+ "throughput_per_second": 1423.187712766563,
+ "allocations": 93,
+ "bytes_allocated": 507754,
+ "retained_bytes": 66080
+ },
+ "warm_samples": [
+ {
+ "iterations": 25,
+ "elapsed_ns": 10338686,
+ "latency_ns": 413547.44,
+ "throughput_per_second": 2418.1022617380972,
+ "allocations": 2322,
+ "bytes_allocated": 12693642,
+ "retained_bytes": 1651792
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 10097811,
+ "latency_ns": 403912.44,
+ "throughput_per_second": 2475.784108060648,
+ "allocations": 2318,
+ "bytes_allocated": 12693258,
+ "retained_bytes": 1651408
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 10332367,
+ "latency_ns": 413294.68,
+ "throughput_per_second": 2419.58110856883,
+ "allocations": 2321,
+ "bytes_allocated": 12693498,
+ "retained_bytes": 1651648
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 10224051,
+ "latency_ns": 408962.04,
+ "throughput_per_second": 2445.214719684008,
+ "allocations": 2315,
+ "bytes_allocated": 12693082,
+ "retained_bytes": 1651232
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 10184134,
+ "latency_ns": 407365.36,
+ "throughput_per_second": 2454.798807635485,
+ "allocations": 2317,
+ "bytes_allocated": 12693322,
+ "retained_bytes": 1651472
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 10514379,
+ "latency_ns": 420575.16,
+ "throughput_per_second": 2377.6962957108544,
+ "allocations": 2327,
+ "bytes_allocated": 12694042,
+ "retained_bytes": 1652192
+ },
+ {
+ "iterations": 25,
+ "elapsed_ns": 10398646,
+ "latency_ns": 415945.84,
+ "throughput_per_second": 2404.159156874847,
+ "allocations": 2322,
+ "bytes_allocated": 12693610,
+ "retained_bytes": 1651760
+ }
+ ],
+ "warm_median": {
+ "iterations": 25,
+ "elapsed_ns": 10332367,
+ "latency_ns": 413294.68,
+ "throughput_per_second": 2419.58110856883,
+ "allocations": 2321,
+ "bytes_allocated": 12693498,
+ "retained_bytes": 1651648
+ }
+ },
+ {
+ "name": "inventory_update",
+ "category": "inventory update",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 6072959,
+ "latency_ns": 6072959.0,
+ "throughput_per_second": 164.66437530699613,
+ "allocations": 2597,
+ "bytes_allocated": 3137859,
+ "retained_bytes": 232425
+ },
+ "warm_samples": [
+ {
+ "iterations": 10000,
+ "elapsed_ns": 9843489,
+ "latency_ns": 984.3489,
+ "throughput_per_second": 1015899.9517345933,
+ "allocations": 62343,
+ "bytes_allocated": 3733421,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 9501934,
+ "latency_ns": 950.1934,
+ "throughput_per_second": 1052417.3289353515,
+ "allocations": 62343,
+ "bytes_allocated": 3733421,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 9721585,
+ "latency_ns": 972.1585,
+ "throughput_per_second": 1028638.8485005274,
+ "allocations": 62343,
+ "bytes_allocated": 3733421,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 9661004,
+ "latency_ns": 966.1004,
+ "throughput_per_second": 1035089.1066808377,
+ "allocations": 62343,
+ "bytes_allocated": 3733421,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 9650449,
+ "latency_ns": 965.0449,
+ "throughput_per_second": 1036221.2162356384,
+ "allocations": 62343,
+ "bytes_allocated": 3733421,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 10181949,
+ "latency_ns": 1018.1949,
+ "throughput_per_second": 982130.2385230962,
+ "allocations": 62343,
+ "bytes_allocated": 3733421,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 10000,
+ "elapsed_ns": 10314490,
+ "latency_ns": 1031.449,
+ "throughput_per_second": 969509.883668509,
+ "allocations": 62343,
+ "bytes_allocated": 3733421,
+ "retained_bytes": 232425
+ }
+ ],
+ "warm_median": {
+ "iterations": 10000,
+ "elapsed_ns": 9721585,
+ "latency_ns": 972.1585,
+ "throughput_per_second": 1028638.8485005274,
+ "allocations": 62343,
+ "bytes_allocated": 3733421,
+ "retained_bytes": 232425
+ }
+ },
+ {
+ "name": "object_update",
+ "category": "object update",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 229485,
+ "latency_ns": 229485.0,
+ "throughput_per_second": 4357.583284310522,
+ "allocations": 1,
+ "bytes_allocated": 323584,
+ "retained_bytes": 0
+ },
+ "warm_samples": [
+ {
+ "iterations": 20000,
+ "elapsed_ns": 550590,
+ "latency_ns": 27.5295,
+ "throughput_per_second": 36324669.899562284,
+ "allocations": 1,
+ "bytes_allocated": 323584,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 543528,
+ "latency_ns": 27.1764,
+ "throughput_per_second": 36796632.372205295,
+ "allocations": 1,
+ "bytes_allocated": 323584,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 543820,
+ "latency_ns": 27.191,
+ "throughput_per_second": 36776874.701187894,
+ "allocations": 1,
+ "bytes_allocated": 323584,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 525060,
+ "latency_ns": 26.253,
+ "throughput_per_second": 38090884.85125509,
+ "allocations": 1,
+ "bytes_allocated": 323584,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 547165,
+ "latency_ns": 27.35825,
+ "throughput_per_second": 36552045.54384875,
+ "allocations": 1,
+ "bytes_allocated": 323584,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 524619,
+ "latency_ns": 26.23095,
+ "throughput_per_second": 38122904.431597024,
+ "allocations": 1,
+ "bytes_allocated": 323584,
+ "retained_bytes": 0
+ },
+ {
+ "iterations": 20000,
+ "elapsed_ns": 532152,
+ "latency_ns": 26.6076,
+ "throughput_per_second": 37583246.89186548,
+ "allocations": 1,
+ "bytes_allocated": 323584,
+ "retained_bytes": 0
+ }
+ ],
+ "warm_median": {
+ "iterations": 20000,
+ "elapsed_ns": 543528,
+ "latency_ns": 27.1764,
+ "throughput_per_second": 36796632.372205295,
+ "allocations": 1,
+ "bytes_allocated": 323584,
+ "retained_bytes": 0
+ }
+ },
+ {
+ "name": "rendering",
+ "category": "rendering",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 21382,
+ "latency_ns": 21382.0,
+ "throughput_per_second": 46768.30979328407,
+ "allocations": 75,
+ "bytes_allocated": 9480,
+ "retained_bytes": 2028
+ },
+ "warm_samples": [
+ {
+ "iterations": 250,
+ "elapsed_ns": 1339889,
+ "latency_ns": 5359.556,
+ "throughput_per_second": 186582.61990358905,
+ "allocations": 18750,
+ "bytes_allocated": 2370000,
+ "retained_bytes": 507000
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 1304705,
+ "latency_ns": 5218.82,
+ "throughput_per_second": 191614.19631257642,
+ "allocations": 18750,
+ "bytes_allocated": 2370000,
+ "retained_bytes": 507000
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 1276452,
+ "latency_ns": 5105.808,
+ "throughput_per_second": 195855.3866498701,
+ "allocations": 18750,
+ "bytes_allocated": 2370000,
+ "retained_bytes": 507000
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 1286930,
+ "latency_ns": 5147.72,
+ "throughput_per_second": 194260.76010350214,
+ "allocations": 18750,
+ "bytes_allocated": 2370000,
+ "retained_bytes": 507000
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 1334780,
+ "latency_ns": 5339.12,
+ "throughput_per_second": 187296.78299045534,
+ "allocations": 18750,
+ "bytes_allocated": 2370000,
+ "retained_bytes": 507000
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 1332218,
+ "latency_ns": 5328.872,
+ "throughput_per_second": 187656.9750596374,
+ "allocations": 18750,
+ "bytes_allocated": 2370000,
+ "retained_bytes": 507000
+ },
+ {
+ "iterations": 250,
+ "elapsed_ns": 1291136,
+ "latency_ns": 5164.544,
+ "throughput_per_second": 193627.93694854763,
+ "allocations": 18750,
+ "bytes_allocated": 2370000,
+ "retained_bytes": 507000
+ }
+ ],
+ "warm_median": {
+ "iterations": 250,
+ "elapsed_ns": 1304705,
+ "latency_ns": 5218.82,
+ "throughput_per_second": 191614.19631257642,
+ "allocations": 18750,
+ "bytes_allocated": 2370000,
+ "retained_bytes": 507000
+ }
+ },
+ {
+ "name": "client_throughput",
+ "category": "client throughput",
+ "unit": "operation",
+ "fixture": "workloads.json",
+ "cold": {
+ "iterations": 1,
+ "elapsed_ns": 5720087,
+ "latency_ns": 5720087.0,
+ "throughput_per_second": 174.8225158113854,
+ "allocations": 2651,
+ "bytes_allocated": 3147905,
+ "retained_bytes": 232425
+ },
+ "warm_samples": [
+ {
+ "iterations": 5000,
+ "elapsed_ns": 31388837,
+ "latency_ns": 6277.7674,
+ "throughput_per_second": 159292.2987239062,
+ "allocations": 322587,
+ "bytes_allocated": 58976737,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 31452023,
+ "latency_ns": 6290.4046,
+ "throughput_per_second": 158972.28613879622,
+ "allocations": 322587,
+ "bytes_allocated": 58976737,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 31177919,
+ "latency_ns": 6235.5838,
+ "throughput_per_second": 160369.90794671062,
+ "allocations": 322587,
+ "bytes_allocated": 58976737,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 31158991,
+ "latency_ns": 6231.7982,
+ "throughput_per_second": 160467.32707102102,
+ "allocations": 322587,
+ "bytes_allocated": 58976737,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 30827722,
+ "latency_ns": 6165.5444,
+ "throughput_per_second": 162191.67929437017,
+ "allocations": 322587,
+ "bytes_allocated": 58976737,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 30766129,
+ "latency_ns": 6153.2258,
+ "throughput_per_second": 162516.38287026618,
+ "allocations": 322587,
+ "bytes_allocated": 58976737,
+ "retained_bytes": 232425
+ },
+ {
+ "iterations": 5000,
+ "elapsed_ns": 30716925,
+ "latency_ns": 6143.385,
+ "throughput_per_second": 162776.71023385317,
+ "allocations": 322587,
+ "bytes_allocated": 58976737,
+ "retained_bytes": 232425
+ }
+ ],
+ "warm_median": {
+ "iterations": 5000,
+ "elapsed_ns": 31158991,
+ "latency_ns": 6231.7982,
+ "throughput_per_second": 160467.32707102102,
+ "allocations": 322587,
+ "bytes_allocated": 58976737,
+ "retained_bytes": 232425
+ }
+ }
+ ]
+}
diff --git a/ci/dependency-policy.json b/ci/dependency-policy.json
index 4dc2129..6993b9d 100644
--- a/ci/dependency-policy.json
+++ b/ci/dependency-policy.json
@@ -2,7 +2,7 @@
"schema": 1,
"msrv": "1.96.0",
"current": "stable",
- "reviewed_on": "2026-08-11",
+ "reviewed_on": "2026-08-12",
"review_by": "2026-11-11",
"direct": [
{ "name": "base64", "versions": ["0.22.1"], "purpose": "LLSD, login, asset, and protocol base64 encoding", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`base64`" },
@@ -27,7 +27,7 @@
{ "name": "sha1", "versions": ["0.10.7"], "purpose": "Legacy protocol hash compatibility", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`sha1`" },
{ "name": "sha2", "versions": ["0.11.0"], "purpose": "Manifest integrity and protocol hashing", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`sha2`" },
{ "name": "skia-safe", "versions": ["0.99.0"], "purpose": "Opt-in cross-platform Skia image decoding", "maintenance": "monitored-native", "transitive_cost": "high", "native": true, "rewrite_anchor": "`skia-safe`" },
- { "name": "stats_alloc", "versions": ["0.1.10"], "purpose": "Allocation-budget compatibility tests and concurrency leak audits", "maintenance": "stable", "transitive_cost": "low", "native": false, "rewrite_anchor": "`stats_alloc`" },
+ { "name": "stats_alloc", "versions": ["0.1.10"], "purpose": "Allocation-budget compatibility tests, concurrency leak audits, and reproducible performance evidence", "maintenance": "stable", "transitive_cost": "low", "native": false, "rewrite_anchor": "`stats_alloc`" },
{ "name": "str0m", "versions": ["0.22.0"], "purpose": "Native Rust ICE, DTLS, SRTP, RTP, and SCTP WebRTC transport", "maintenance": "active", "transitive_cost": "high", "native": false, "rewrite_anchor": "`str0m`" },
{ "name": "syn", "versions": ["2.0.119"], "purpose": "Syntax validation for generated Rust sources", "maintenance": "active", "transitive_cost": "medium", "native": false, "rewrite_anchor": "`syn`" },
{ "name": "tar", "versions": ["0.4.46"], "purpose": "Bounded OAR and asset archive traversal", "maintenance": "active", "transitive_cost": "low", "native": false, "rewrite_anchor": "`tar`" },
diff --git a/ci/provenance-policy.json b/ci/provenance-policy.json
index 8cbe3c0..aaf1634 100644
--- a/ci/provenance-policy.json
+++ b/ci/provenance-policy.json
@@ -36,6 +36,12 @@
{"path":"codegen/inputs/lsl_tools_grammar.json","sha256":"2496b7acc247c5aa927017ff2f2580f704ced17a85977d3bf926d31f17b04234","kind":"derived-grammar","origin":"LibreMetaverse.LslTools/YYClass/yycs0syntax.cs and yycs0tokens.cs","license":"BSD-3-Clause","distribution":"source-and-generated-code"},
{"path":"tests/fixtures/structured_data/json_reference.json","sha256":"97b18e725932a3192a21d6c12e6ab29236957b90f749e738b7dbbea44498afbc","kind":"project-fixture","origin":"MetaCrate JSON OSD compatibility fixture","license":"BSD-3-Clause","distribution":"source-only"},
{"path":"tests/fixtures/structured_data/protobuf_reference.hex","sha256":"6c87c73097eb68a8e20bba6c146da8ef2ad3c71452407da497cb7296a02f8b7d","kind":"project-fixture","origin":"MetaCrate Protobuf OSD compatibility fixture","license":"BSD-3-Clause","distribution":"source-only"},
+ {"path":"benchmarks/fixtures/agent_pause.packet","sha256":"ec6febce906a5c7b2dcb08e089a2b1dcf446e42655f90e61de4f37356b0026e5","kind":"project-benchmark-fixture","origin":"MetaCrate reproducible AgentPause packet fixture","license":"BSD-3-Clause","distribution":"source-only"},
+ {"path":"benchmarks/fixtures/image.tga","sha256":"8864774adaf571530ff4287288bb6f6ca1b7e88dc1f4bec04c6f79e13a159582","kind":"project-benchmark-fixture","origin":"MetaCrate reproducible TGA image fixture","license":"BSD-3-Clause","distribution":"source-only"},
+ {"path":"benchmarks/fixtures/manifest.json","sha256":"1b8730a08b7740b91de7d6e46595e04ee5f09613ef478313203959e7a29b3145","kind":"project-benchmark-manifest","origin":"MetaCrate reproducible benchmark fixture hashes","license":"BSD-3-Clause","distribution":"source-only"},
+ {"path":"benchmarks/fixtures/mesh_asset.bin","sha256":"4f665cf5396999e696fa49053e930b8b9ad9eda44ae85df22a6f0dbbd2fc6684","kind":"project-benchmark-fixture","origin":"MetaCrate reproducible mesh asset fixture","license":"BSD-3-Clause","distribution":"source-only"},
+ {"path":"benchmarks/fixtures/notecard.txt","sha256":"b796c40a34ff00dbabc5d3f94e518154528bb87cf7f3a8262b1a5ab6e5ad7e1b","kind":"project-benchmark-fixture","origin":"MetaCrate reproducible notecard asset fixture","license":"BSD-3-Clause","distribution":"source-only"},
+ {"path":"benchmarks/fixtures/workloads.json","sha256":"9124763e4822e57850783c06b37cd569355f73ac2397bca85f6dd89e0470267d","kind":"project-benchmark-config","origin":"MetaCrate reproducible workload dimensions","license":"BSD-3-Clause","distribution":"source-only"},
{"path":"fuzz/corpus/binary_llsd/malformed.hex","sha256":"7e0f49303f07a638a8d2fba637ac7fab1e63386c9b4e6b46730425e87d15fcbe","kind":"project-security-corpus","origin":"MetaCrate parser hardening cases","license":"BSD-3-Clause","distribution":"source-only"},
{"path":"fuzz/corpus/json_osd/malformed.txt","sha256":"a1b326b59db9d59a1f4ba9f6e58aa58e77bc7e160600844e76f7b0f09b44b39a","kind":"project-security-corpus","origin":"MetaCrate parser hardening cases","license":"BSD-3-Clause","distribution":"source-only"},
{"path":"fuzz/corpus/notation_llsd/malformed.txt","sha256":"e87c4ad58f40cc0703b771a522bf5edd7c1768bb26336169502553866f070bd1","kind":"project-security-corpus","origin":"MetaCrate parser hardening cases","license":"BSD-3-Clause","distribution":"source-only"},
diff --git a/crates/libremetaverse/src/inventory.rs b/crates/libremetaverse/src/inventory.rs
index fb3a45d..9386380 100644
--- a/crates/libremetaverse/src/inventory.rs
+++ b/crates/libremetaverse/src/inventory.rs
@@ -1706,6 +1706,44 @@ impl Inventory {
let parent_uuid = value.base().parent_uuid;
let event = {
let mut state = write(&self.inner.state);
+ // Root-level records have no hierarchy edges or ancestor counts to
+ // rebuild. They are common during the initial flat inventory feed
+ // and for incremental item refreshes, so update their node and link
+ // index directly instead of walking and relocking the entire store.
+ // The general path below remains responsible for moves, folders,
+ // cycles, placeholder parents, and descendant counts.
+ let old_root_value = state
+ .items
+ .get(&uuid)
+ .and_then(InventoryNode::value)
+ .filter(|old| old.base().parent_uuid == UUID::zero());
+ if parent_uuid == UUID::zero()
+ && (old_root_value.is_some() || !state.items.contains_key(&uuid))
+ {
+ if let Some(old) = old_root_value.as_ref() {
+ update_link_index(&mut state.links, uuid, old, false);
+ }
+ update_link_index(&mut state.links, uuid, &value, true);
+ let event = if let Some(node) = state.items.get(&uuid) {
+ let old = node.value();
+ node.set_value(value.clone());
+ old.map(|old| InventoryObjectUpdatedEventArgs::from_values(old, value.clone()))
+ } else {
+ state
+ .items
+ .insert(uuid, InventoryNode::from_value(value.clone()));
+ None
+ };
+ drop(state);
+ if let Some(event) = event {
+ self.inner.updated.emit(event);
+ } else {
+ self.inner
+ .added
+ .emit(InventoryObjectAddedEventArgs::from_value(value));
+ }
+ return Ok(());
+ }
if parent_uuid != UUID::zero() && !state.items.contains_key(&parent_uuid) {
let mut fake = InventoryFolder::new(parent_uuid)?;
fake.version = InventoryFolder::VERSION_UNKNOWN;
@@ -1865,6 +1903,28 @@ impl Inventory {
}
}
+fn update_link_index(
+ links: &mut HashMap>,
+ uuid: UUID,
+ value: &InventoryValue,
+ insert: bool,
+) {
+ let Some(item) = value.item() else {
+ return;
+ };
+ if !item.is_link().unwrap_or(false) || item.asset_uuid == UUID::zero() {
+ return;
+ }
+ if insert {
+ links.entry(item.asset_uuid).or_default().insert(uuid);
+ } else if let Some(records) = links.get_mut(&item.asset_uuid) {
+ records.remove(&uuid);
+ if records.is_empty() {
+ links.remove(&item.asset_uuid);
+ }
+ }
+}
+
fn rebuild_indexes_and_counts(state: &mut InventoryState) {
state.links.clear();
let nodes: Vec<_> = state.items.values().cloned().collect();
@@ -2944,6 +3004,29 @@ mod tests {
assert_eq!(calls.load(Ordering::SeqCst), 1);
}
+ #[test]
+ fn root_item_fast_path_keeps_link_index_and_events_consistent() {
+ let (_client, inventory) = fixture();
+ let item_id = UUID::random().unwrap();
+ let first_target = UUID::random().unwrap();
+ let second_target = UUID::random().unwrap();
+ let mut item = InventoryItem::new_with_uuid(item_id).unwrap();
+ item.set_asset_type(AssetType::Link);
+ item.set_asset_uuid(first_target);
+ inventory.update_node_for(&item).unwrap();
+ assert_eq!(inventory.find_all_links(first_target).unwrap().len(), 1);
+
+ item.set_asset_uuid(second_target);
+ inventory.update_node_for(&item).unwrap();
+ assert!(inventory.find_all_links(first_target).unwrap().is_empty());
+ assert_eq!(inventory.find_all_links(second_target).unwrap().len(), 1);
+
+ item.set_asset_type(AssetType::Texture);
+ inventory.update_node_for(&item).unwrap();
+ assert!(inventory.find_all_links(second_target).unwrap().is_empty());
+ assert_eq!(inventory.count(), 1);
+ }
+
#[test]
fn system_folders_sort_first_and_are_discoverable() {
let (_client, mut inventory) = fixture();
diff --git a/crates/libremetaverse/src/targa.rs b/crates/libremetaverse/src/targa.rs
index b097d70..a206faf 100644
--- a/crates/libremetaverse/src/targa.rs
+++ b/crates/libremetaverse/src/targa.rs
@@ -11,6 +11,16 @@ type TgaPalette = (usize, Vec<[u8; 4]>);
pub struct Targa;
impl Targa {
+ /// Decodes an in-memory TGA or DDS payload without copying it through the
+ /// compatibility stream boundary.
+ ///
+ /// # Errors
+ ///
+ /// Returns a typed error for oversized, malformed, or unsupported input.
+ pub fn decode_to_managed_image_with_bytes(data: &[u8]) -> Result {
+ decode(data)
+ }
+
/// Decodes a TGA or DDS file into planar managed-image storage.
///
/// # Errors
@@ -185,6 +195,15 @@ fn decode_tga(bytes: &[u8]) -> Result {
return Err(parse(18, "truncated TGA image ID"));
}
let palette = read_tga_palette(bytes, header, has_color_map, color_mapped, &mut position)?;
+ if !rle
+ && !grayscale
+ && palette.is_none()
+ && matches!(depth, 24 | 32)
+ && header[17] & 0x30 == 0x20
+ {
+ decode_plain_truecolor(bytes, position, pixels, pixel_bytes, depth, &mut image)?;
+ return Ok(image);
+ }
let mut decoded = 0;
while decoded < pixels {
let (count, repeated) = if rle {
@@ -238,6 +257,30 @@ fn decode_tga(bytes: &[u8]) -> Result {
Ok(image)
}
+fn decode_plain_truecolor(
+ bytes: &[u8],
+ position: usize,
+ pixels: usize,
+ pixel_bytes: usize,
+ depth: u8,
+ image: &mut ManagedImage,
+) -> Result<(), Error> {
+ let byte_length = pixels.checked_mul(pixel_bytes).ok_or(Error::Argument)?;
+ let end = position.checked_add(byte_length).ok_or(Error::Argument)?;
+ let data = bytes
+ .get(position..end)
+ .ok_or_else(|| parse(position, "truncated TGA pixel data"))?;
+ for (target, pixel) in data.chunks_exact(pixel_bytes).enumerate() {
+ image.blue[target] = pixel[0];
+ image.green[target] = pixel[1];
+ image.red[target] = pixel[2];
+ if depth == 32 {
+ image.alpha[target] = pixel[3];
+ }
+ }
+ Ok(())
+}
+
fn tga_channels(
grayscale: bool,
color_mapped: bool,
diff --git a/crates/libremetaverse/tests/performance_regressions.rs b/crates/libremetaverse/tests/performance_regressions.rs
new file mode 100644
index 0000000..1fc0d0c
--- /dev/null
+++ b/crates/libremetaverse/tests/performance_regressions.rs
@@ -0,0 +1,44 @@
+use std::sync::Arc;
+
+use libremetaverse::imaging::Targa;
+use libremetaverse::{GridClient, Inventory, InventoryItem};
+use libremetaverse_types::{AssetType, UUID};
+
+#[test]
+fn root_inventory_updates_preserve_link_index() {
+ let client = Arc::new(GridClient::new().expect("offline client"));
+ let inventory = Inventory::new_with_grid_client_uuid(client, UUID::zero()).expect("store");
+ let item_id = UUID::new_with_u_int64(1).expect("item UUID");
+ let first_target = UUID::new_with_u_int64(2).expect("first target");
+ let second_target = UUID::new_with_u_int64(3).expect("second target");
+ let mut item = InventoryItem::new_with_uuid(item_id).expect("item");
+ item.set_asset_type(AssetType::Link);
+ item.set_asset_uuid(first_target);
+ inventory.update_node_for(&item).expect("insert root link");
+ assert_eq!(inventory.find_all_links(first_target).unwrap().len(), 1);
+
+ item.set_asset_uuid(second_target);
+ inventory
+ .update_node_for(&item)
+ .expect("retarget root link");
+ assert!(inventory.find_all_links(first_target).unwrap().is_empty());
+ assert_eq!(inventory.find_all_links(second_target).unwrap().len(), 1);
+
+ item.set_asset_type(AssetType::Texture);
+ inventory.update_node_for(&item).expect("replace link");
+ assert!(inventory.find_all_links(second_target).unwrap().is_empty());
+ assert_eq!(inventory.count(), 1);
+}
+
+#[test]
+fn borrowed_tga_fast_path_preserves_fixture_pixels() {
+ let bytes = include_bytes!("../../../benchmarks/fixtures/image.tga");
+ let image = Targa::decode_to_managed_image_with_bytes(bytes).expect("decode TGA fixture");
+ assert_eq!((image.width, image.height), (128, 128));
+ assert_eq!(image.red.len(), 128 * 128);
+ assert_eq!(
+ (&image.red[..4], &image.green[..4], &image.blue[..4]),
+ (&[0, 1, 2, 3][..], &[0, 3, 6, 9][..], &[0, 7, 14, 21][..])
+ );
+ assert!(image.alpha.iter().all(|value| *value == u8::MAX));
+}
diff --git a/release/DEPENDENCY-LICENSES.json b/release/DEPENDENCY-LICENSES.json
index 8f726a1..a39b42c 100644
--- a/release/DEPENDENCY-LICENSES.json
+++ b/release/DEPENDENCY-LICENSES.json
@@ -1,6 +1,6 @@
{
"schema": 1,
- "cargo_lock_sha256": "c772cdfb50bc3a9160b135355f0d7a89fd7055dc5df0c876e7245deabd2c4812",
+ "cargo_lock_sha256": "ff5b851139156d43915f08494c5723638d3b48abb9d7ab5de6eea9e9f5b5554b",
"packages": [
{
"name": "adler2",
diff --git a/release/DISTRIBUTION-MANIFEST.json b/release/DISTRIBUTION-MANIFEST.json
index 2736666..de6b1c9 100644
--- a/release/DISTRIBUTION-MANIFEST.json
+++ b/release/DISTRIBUTION-MANIFEST.json
@@ -1,7 +1,7 @@
{
"schema": 1,
- "cargo_lock_sha256": "c772cdfb50bc3a9160b135355f0d7a89fd7055dc5df0c876e7245deabd2c4812",
- "provenance_policy_sha256": "188ac430e8c804a8b40153c3dca05affd869a6e05abab80fcccbc2d46ff0ee2e",
+ "cargo_lock_sha256": "ff5b851139156d43915f08494c5723638d3b48abb9d7ab5de6eea9e9f5b5554b",
+ "provenance_policy_sha256": "045859dcf317efc19e6e47fc73dfc15726f7a787556a3960c4732aa5f3afde7c",
"upstream_repository": "https://github.com/cinderblocks/libremetaverse",
"upstream_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba",
"source_files": [
@@ -40,6 +40,11 @@
"bytes": 1607,
"sha256": "f7a23f0c89bb9476fffc3036b257ab8022a7af8b3b3ecd586d98cb7d76a23db6"
},
+ {
+ "path": ".gitea/workflows/performance.yml",
+ "bytes": 1855,
+ "sha256": "bafd171f15b6e83e52f07f85836f5807a822d2016f4c75901b242623a092a6fb"
+ },
{
"path": ".gitea/workflows/release-matrix.yml",
"bytes": 4196,
@@ -72,13 +77,13 @@
},
{
"path": "Cargo.lock",
- "bytes": 99105,
- "sha256": "c772cdfb50bc3a9160b135355f0d7a89fd7055dc5df0c876e7245deabd2c4812"
+ "bytes": 99427,
+ "sha256": "ff5b851139156d43915f08494c5723638d3b48abb9d7ab5de6eea9e9f5b5554b"
},
{
"path": "Cargo.toml",
- "bytes": 1455,
- "sha256": "b40542879b5e6e2421053dfcf46cee9611a8edfd4eafb39c3346986744ddcf56"
+ "bytes": 1480,
+ "sha256": "fa9a7e393968e0080672245dc7dc05b046c51307cdf734cc176f183e1d2e7404"
},
{
"path": "LICENSE.md",
@@ -160,6 +165,76 @@
"bytes": 47154083,
"sha256": "618974cf09bfd1e051ae7a3a35e01ca3b1a8b64b919bcbf153860290d137ce94"
},
+ {
+ "path": "benchmarks/README.md",
+ "bytes": 4567,
+ "sha256": "f5fa11f3c977d59b43082dd86718c5c4b986f78b401b71993186f3bd3904511a"
+ },
+ {
+ "path": "benchmarks/REPORT.md",
+ "bytes": 2584,
+ "sha256": "26224aed892c7b63c2c97c3a82cfaaa4b758ec1e18013addd594c0093e162ef3"
+ },
+ {
+ "path": "benchmarks/csharp-reference/MetaCrate.ReferenceBenchmarks.csproj",
+ "bytes": 790,
+ "sha256": "c6ffc4c9ede90f4160cd2c802f368ce7fdc08c43041597b7910ccc7502df8a88"
+ },
+ {
+ "path": "benchmarks/csharp-reference/Program.cs",
+ "bytes": 15208,
+ "sha256": "8b6e0c3abf1abf97fde76ba356f00d2e7c21fda176d3a9f7da52d598b48c34eb"
+ },
+ {
+ "path": "benchmarks/fixtures/agent_pause.packet",
+ "bytes": 46,
+ "sha256": "ec6febce906a5c7b2dcb08e089a2b1dcf446e42655f90e61de4f37356b0026e5"
+ },
+ {
+ "path": "benchmarks/fixtures/image.tga",
+ "bytes": 65568,
+ "sha256": "8864774adaf571530ff4287288bb6f6ca1b7e88dc1f4bec04c6f79e13a159582"
+ },
+ {
+ "path": "benchmarks/fixtures/manifest.json",
+ "bytes": 440,
+ "sha256": "1b8730a08b7740b91de7d6e46595e04ee5f09613ef478313203959e7a29b3145"
+ },
+ {
+ "path": "benchmarks/fixtures/mesh_asset.bin",
+ "bytes": 26921,
+ "sha256": "4f665cf5396999e696fa49053e930b8b9ad9eda44ae85df22a6f0dbbd2fc6684"
+ },
+ {
+ "path": "benchmarks/fixtures/notecard.txt",
+ "bytes": 208,
+ "sha256": "b796c40a34ff00dbabc5d3f94e518154528bb87cf7f3a8262b1a5ab6e5ad7e1b"
+ },
+ {
+ "path": "benchmarks/fixtures/workloads.json",
+ "bytes": 636,
+ "sha256": "9124763e4822e57850783c06b37cd569355f73ac2397bca85f6dd89e0470267d"
+ },
+ {
+ "path": "benchmarks/release-criteria.json",
+ "bytes": 986,
+ "sha256": "c3516ed91258bb900699d432ccdc9e3f69e120c92f580cf46fcca3eea0cd4f1f"
+ },
+ {
+ "path": "benchmarks/results/comparison.json",
+ "bytes": 7252,
+ "sha256": "fdcc62d12a5d73a9ce75374f808226cff36f452332388b575a4d95c45a7d8cb9"
+ },
+ {
+ "path": "benchmarks/results/csharp-linux-x86_64.json",
+ "bytes": 37903,
+ "sha256": "4bae693cdc712dc2ce8039121d9511042c098fa07dfece8f50e57cc91a957aaa"
+ },
+ {
+ "path": "benchmarks/results/rust-linux-x86_64.json",
+ "bytes": 37699,
+ "sha256": "9ffc240ca35d397ee848a6b313efcfefcf186ea01f61911aa3329cb2dcefd202"
+ },
{
"path": "ci/concurrency-thresholds.json",
"bytes": 169,
@@ -167,8 +242,8 @@
},
{
"path": "ci/dependency-policy.json",
- "bytes": 10329,
- "sha256": "6d2ddc20ba92dc51645cdddd39817ad84d1ad1a9d02c5532e499ff91d729b2dc"
+ "bytes": 10365,
+ "sha256": "4f545b31c6ea2d97eadc5a60423d13839cc9a71447a603806a8690de4c56f226"
},
{
"path": "ci/evidence/api-audit.json",
@@ -187,8 +262,8 @@
},
{
"path": "ci/provenance-policy.json",
- "bytes": 9684,
- "sha256": "188ac430e8c804a8b40153c3dca05affd869a6e05abab80fcccbc2d46ff0ee2e"
+ "bytes": 11311,
+ "sha256": "045859dcf317efc19e6e47fc73dfc15726f7a787556a3960c4732aa5f3afde7c"
},
{
"path": "ci/release-matrix.json",
@@ -987,8 +1062,8 @@
},
{
"path": "crates/libremetaverse/src/inventory.rs",
- "bytes": 103729,
- "sha256": "7b4ac24b66c8371cedefcbd7dbeb141d7a7927e731e6823c8cdfef84617d1d80"
+ "bytes": 107222,
+ "sha256": "d4fe66be383f8c88cbe523315c6edb02044e4585e328eb432f8c422a095d3035"
},
{
"path": "crates/libremetaverse/src/inventory_ais.rs",
@@ -1102,8 +1177,8 @@
},
{
"path": "crates/libremetaverse/src/targa.rs",
- "bytes": 45068,
- "sha256": "c74ce84eb97d0e3e211e3a2039b2538399c648dcb4809d0f0e8c03d00281761d"
+ "bytes": 46419,
+ "sha256": "20c66897bca7787a3bfb363294f9b00aa766e29d6bd5779d3170a874cc50660b"
},
{
"path": "crates/libremetaverse/src/terrain_codec.rs",
@@ -1175,6 +1250,11 @@
"bytes": 6544,
"sha256": "07233faf32417f605cf29c275a4c70c12e8b1960434f247f16bc02148dace6db"
},
+ {
+ "path": "crates/libremetaverse/tests/performance_regressions.rs",
+ "bytes": 1944,
+ "sha256": "a21ad12e32b5fdb9e6cb29c3cba1326c548a22b2a0222978ee4d4e0321a55bbb"
+ },
{
"path": "crates/libremetaverse/tests/udp_transport.rs",
"bytes": 17729,
@@ -2182,8 +2262,8 @@
},
{
"path": "tools/ci-matrix/src/provenance.rs",
- "bytes": 44192,
- "sha256": "59146a9426f4d6f515084cbca7a91b4c98589066620e6f3ef48dc30aa8b90fb4"
+ "bytes": 44234,
+ "sha256": "d9421c261ba99e68d1eba2c4606cbf63f8d9dc61b87d36f5a696afec1efeadb1"
},
{
"path": "tools/codegen/Cargo.toml",
@@ -2250,6 +2330,16 @@
"bytes": 2085,
"sha256": "cece0ccb847dfc015734297b6988752d140e15a44f5347236266d2af699f7052"
},
+ {
+ "path": "tools/performance/Cargo.toml",
+ "bytes": 901,
+ "sha256": "6621825fb0de082d035c3ac9855009a33afdf5d0d2189cd3d72e0a3e2c1babb4"
+ },
+ {
+ "path": "tools/performance/src/main.rs",
+ "bytes": 35323,
+ "sha256": "412c56a136c7e0fe2e51c1ba323e6377e2bec69aa11ae602436abc87348f7e4c"
+ },
{
"path": "tools/test_audit_red_suite.py",
"bytes": 1212,
@@ -2275,7 +2365,7 @@
{
"path": "release/DEPENDENCY-LICENSES.json",
"bytes": 215927,
- "sha256": "f2f8c01d5994e8b1d5568f4f678456de7f0a77aa54e29fa8e1c534f4060bd073"
+ "sha256": "1644915765f829b6476cfa65f2105f8dead39ca0e65640c87bfb497e5d873d0e"
},
{
"path": "release/THIRD-PARTY-NOTICES.md",
@@ -2377,6 +2467,54 @@
"license": "BSD-3-Clause",
"distribution": "source-only"
},
+ {
+ "path": "benchmarks/fixtures/agent_pause.packet",
+ "sha256": "ec6febce906a5c7b2dcb08e089a2b1dcf446e42655f90e61de4f37356b0026e5",
+ "kind": "project-benchmark-fixture",
+ "origin": "MetaCrate reproducible AgentPause packet fixture",
+ "license": "BSD-3-Clause",
+ "distribution": "source-only"
+ },
+ {
+ "path": "benchmarks/fixtures/image.tga",
+ "sha256": "8864774adaf571530ff4287288bb6f6ca1b7e88dc1f4bec04c6f79e13a159582",
+ "kind": "project-benchmark-fixture",
+ "origin": "MetaCrate reproducible TGA image fixture",
+ "license": "BSD-3-Clause",
+ "distribution": "source-only"
+ },
+ {
+ "path": "benchmarks/fixtures/manifest.json",
+ "sha256": "1b8730a08b7740b91de7d6e46595e04ee5f09613ef478313203959e7a29b3145",
+ "kind": "project-benchmark-manifest",
+ "origin": "MetaCrate reproducible benchmark fixture hashes",
+ "license": "BSD-3-Clause",
+ "distribution": "source-only"
+ },
+ {
+ "path": "benchmarks/fixtures/mesh_asset.bin",
+ "sha256": "4f665cf5396999e696fa49053e930b8b9ad9eda44ae85df22a6f0dbbd2fc6684",
+ "kind": "project-benchmark-fixture",
+ "origin": "MetaCrate reproducible mesh asset fixture",
+ "license": "BSD-3-Clause",
+ "distribution": "source-only"
+ },
+ {
+ "path": "benchmarks/fixtures/notecard.txt",
+ "sha256": "b796c40a34ff00dbabc5d3f94e518154528bb87cf7f3a8262b1a5ab6e5ad7e1b",
+ "kind": "project-benchmark-fixture",
+ "origin": "MetaCrate reproducible notecard asset fixture",
+ "license": "BSD-3-Clause",
+ "distribution": "source-only"
+ },
+ {
+ "path": "benchmarks/fixtures/workloads.json",
+ "sha256": "9124763e4822e57850783c06b37cd569355f73ac2397bca85f6dd89e0470267d",
+ "kind": "project-benchmark-config",
+ "origin": "MetaCrate reproducible workload dimensions",
+ "license": "BSD-3-Clause",
+ "distribution": "source-only"
+ },
{
"path": "fuzz/corpus/binary_llsd/malformed.hex",
"sha256": "7e0f49303f07a638a8d2fba637ac7fab1e63386c9b4e6b46730425e87d15fcbe",
diff --git a/tools/ci-matrix/src/provenance.rs b/tools/ci-matrix/src/provenance.rs
index c6ac01c..a878718 100644
--- a/tools/ci-matrix/src/provenance.rs
+++ b/tools/ci-matrix/src/provenance.rs
@@ -22,7 +22,12 @@ const GENERATED_RELEASE_PATHS: [&str; 4] = [
NATIVE_NOTICE_PATH,
DISTRIBUTION_MANIFEST_PATH,
];
-const MATERIAL_ROOTS: [&str; 3] = ["codegen/inputs", "tests/fixtures", "fuzz/corpus"];
+const MATERIAL_ROOTS: [&str; 4] = [
+ "codegen/inputs",
+ "tests/fixtures",
+ "fuzz/corpus",
+ "benchmarks/fixtures",
+];
const BUNDLED_EXTENSIONS: [&str; 18] = [
"a", "animatn", "bmp", "bodypart", "clothing", "dll", "dylib", "gesture", "gif", "jpeg", "jpg",
"llm", "ogg", "png", "so", "tga", "wav", "webp",
diff --git a/tools/performance/Cargo.toml b/tools/performance/Cargo.toml
new file mode 100644
index 0000000..1cbb65e
--- /dev/null
+++ b/tools/performance/Cargo.toml
@@ -0,0 +1,24 @@
+[package]
+name = "metacrate-performance"
+version.workspace = true
+edition.workspace = true
+rust-version.workspace = true
+license.workspace = true
+repository.workspace = true
+description = "Reproducible cross-runtime performance evidence for MetaCrate"
+publish = false
+
+[dependencies]
+libremetaverse = { path = "../../crates/libremetaverse" }
+libremetaverse-imaging = { path = "../../crates/libremetaverse-imaging" }
+libremetaverse-rendering-mesh-foundry = { path = "../../crates/libremetaverse-rendering-mesh-foundry" }
+libremetaverse-rendering-simple = { path = "../../crates/libremetaverse-rendering-simple" }
+libremetaverse-structured-data = { path = "../../crates/libremetaverse-structured-data" }
+libremetaverse-types = { path = "../../crates/libremetaverse-types" }
+serde = { version = "1", features = ["derive"] }
+serde_json = "1"
+sha2 = "0.11"
+stats_alloc = "0.1.10"
+
+[lints]
+workspace = true
diff --git a/tools/performance/src/main.rs b/tools/performance/src/main.rs
new file mode 100644
index 0000000..da00504
--- /dev/null
+++ b/tools/performance/src/main.rs
@@ -0,0 +1,1026 @@
+#![allow(clippy::cast_precision_loss)]
+
+use std::alloc::System;
+use std::collections::{BTreeMap, BTreeSet, HashMap};
+use std::fs;
+use std::hint::black_box;
+use std::path::Path;
+use std::sync::Arc;
+use std::time::Instant;
+
+use libremetaverse::assets::AssetNotecard;
+use libremetaverse::imaging::Targa;
+use libremetaverse::import_export::{ModelFace, ModelPrim};
+use libremetaverse::messages::linden::RemoteParcelRequestReply;
+use libremetaverse::packets::AgentPausePacket;
+use libremetaverse::rendering::{DetailLevel, Vertex};
+use libremetaverse::{GridClient, Inventory, InventoryItem, Primitive, PrimitiveConstructionData};
+use libremetaverse_imaging::{ManagedImage, ManagedImageImageChannels};
+use libremetaverse_rendering_mesh_foundry::MeshFoundry;
+use libremetaverse_rendering_simple::SimpleRenderer;
+use libremetaverse_structured_data::{OSD, OSDParser};
+use libremetaverse_types::{
+ HoleType, Matrix4, PCode, PathCurve, ProfileCurve, Quaternion, UUID, Vector2, Vector3,
+};
+use serde::{Deserialize, Serialize};
+use sha2::{Digest, Sha256};
+use stats_alloc::{INSTRUMENTED_SYSTEM, Region, Stats, StatsAlloc};
+
+#[global_allocator]
+static ALLOCATOR: &StatsAlloc = &INSTRUMENTED_SYSTEM;
+
+const RUNS: usize = 7;
+const TOOL_SCHEMA: u32 = 1;
+const EXPECTED_REFERENCE: &str = "2aa70bb68513b39795da5d13c88f31b86e85a3ba";
+
+type AppResult = Result;
+
+#[derive(Clone, Deserialize)]
+struct Fixture {
+ schema: u32,
+ reference_commit: String,
+ uuid: String,
+ uuid_math_iterations: usize,
+ llsd_iterations: usize,
+ packet_iterations: usize,
+ asset_iterations: usize,
+ image_iterations: usize,
+ mesh_iterations: usize,
+ inventory_iterations: usize,
+ object_iterations: usize,
+ rendering_iterations: usize,
+ client_iterations: usize,
+ warmup_divisor: usize,
+ llsd_array_length: usize,
+ packet_blocks: usize,
+ image_width: i32,
+ image_height: i32,
+ mesh_side: usize,
+ inventory_items: usize,
+ object_count: usize,
+ client_batch: usize,
+}
+
+#[derive(Serialize, Deserialize)]
+struct Environment {
+ os: String,
+ arch: String,
+ logical_cpus: usize,
+ toolchain: String,
+ profile: String,
+}
+
+#[derive(Clone, Serialize, Deserialize)]
+struct Metrics {
+ iterations: usize,
+ elapsed_ns: u128,
+ latency_ns: f64,
+ throughput_per_second: f64,
+ allocations: Option,
+ bytes_allocated: usize,
+ retained_bytes: i128,
+}
+
+#[derive(Serialize, Deserialize)]
+struct BenchmarkResult {
+ name: String,
+ category: String,
+ unit: String,
+ fixture: String,
+ cold: Metrics,
+ warm_samples: Vec,
+ warm_median: Metrics,
+}
+
+#[derive(Serialize, Deserialize)]
+struct Report {
+ schema: u32,
+ runtime: String,
+ reference_commit: String,
+ fixture_hashes: BTreeMap,
+ environment: Environment,
+ results: Vec,
+}
+
+struct Context {
+ fixture: Fixture,
+ uuid: UUID,
+ llsd: OSD,
+ packet: Vec,
+ notecard: Vec,
+ image: Vec,
+ mesh: Vec,
+}
+
+#[derive(Clone, Copy)]
+struct Workload {
+ name: &'static str,
+ category: &'static str,
+ fixture: &'static str,
+ iterations: fn(&Fixture) -> usize,
+ run: fn(&Context, usize) -> AppResult,
+}
+
+fn main() {
+ if let Err(error) = run_cli() {
+ eprintln!("performance audit failed: {error}");
+ std::process::exit(1);
+ }
+}
+
+fn run_cli() -> AppResult<()> {
+ let args: Vec = std::env::args().skip(1).collect();
+ match args.first().map(String::as_str) {
+ Some("fixtures") => {
+ let root =
+ value(&args, "--fixture-root").unwrap_or_else(|| "benchmarks/fixtures".into());
+ generate_fixtures(Path::new(&root))
+ }
+ Some("run") => {
+ let root =
+ value(&args, "--fixture-root").unwrap_or_else(|| "benchmarks/fixtures".into());
+ let output = value(&args, "--output")
+ .unwrap_or_else(|| "benchmarks/results/rust-linux-x86_64.json".into());
+ let report = run_benchmarks(Path::new(&root))?;
+ write_json(Path::new(&output), &report)
+ }
+ Some("compare") => {
+ let rust = required(&args, "--rust")?;
+ let reference = required(&args, "--reference")?;
+ let output = required(&args, "--output")?;
+ compare_reports(Path::new(&rust), Path::new(&reference), Path::new(&output))
+ }
+ Some("audit") => {
+ let root =
+ value(&args, "--fixture-root").unwrap_or_else(|| "benchmarks/fixtures".into());
+ let rust = required(&args, "--rust")?;
+ let reference = required(&args, "--reference")?;
+ let comparison = required(&args, "--comparison")?;
+ audit(
+ Path::new(&root),
+ Path::new(&rust),
+ Path::new(&reference),
+ Path::new(&comparison),
+ )
+ }
+ _ => Err("usage: metacrate-performance [options]".into()),
+ }
+}
+
+fn value(args: &[String], key: &str) -> Option {
+ args.windows(2)
+ .find(|pair| pair[0] == key)
+ .map(|pair| pair[1].clone())
+}
+
+fn required(args: &[String], key: &str) -> AppResult {
+ value(args, key).ok_or_else(|| format!("missing {key}"))
+}
+
+fn fixture(path: &Path) -> AppResult {
+ let bytes = fs::read(path).map_err(|error| format!("read {}: {error}", path.display()))?;
+ let fixture: Fixture = serde_json::from_slice(&bytes)
+ .map_err(|error| format!("parse {}: {error}", path.display()))?;
+ if fixture.schema != 1 || fixture.reference_commit != EXPECTED_REFERENCE {
+ return Err("fixture schema or pinned reference commit does not match policy".into());
+ }
+ if fixture.warmup_divisor == 0 {
+ return Err("warmup_divisor must be nonzero".into());
+ }
+ Ok(fixture)
+}
+
+fn generate_fixtures(root: &Path) -> AppResult<()> {
+ fs::create_dir_all(root).map_err(|error| error.to_string())?;
+ let config = fixture(&root.join("workloads.json"))?;
+
+ let mut image = ManagedImage::new(
+ config.image_width,
+ config.image_height,
+ ManagedImageImageChannels(
+ ManagedImageImageChannels::COLOR.0 | ManagedImageImageChannels::ALPHA.0,
+ ),
+ )
+ .map_err(debug)?;
+ for index in 0..image.red.len() {
+ image.red[index] = u8::try_from(index & 255).map_err(debug)?;
+ image.green[index] = u8::try_from((index * 3) & 255).map_err(debug)?;
+ image.blue[index] = u8::try_from((index * 7) & 255).map_err(debug)?;
+ image.alpha[index] = 255;
+ }
+ fs::write(root.join("image.tga"), Targa::encode(image).map_err(debug)?)
+ .map_err(|error| error.to_string())?;
+
+ let mut model = ModelPrim::new().map_err(debug)?;
+ let mut face = ModelFace::new().map_err(debug)?;
+ let side = config.mesh_side;
+ for y in 0..side {
+ for x in 0..side {
+ let u = x as f32 / (side - 1) as f32;
+ let v = y as f32 / (side - 1) as f32;
+ face.vertices.push(Vertex {
+ position: Vector3 {
+ x: u - 0.5,
+ y: v - 0.5,
+ z: (u * std::f32::consts::TAU).sin() * 0.05,
+ },
+ normal: Vector3::unit_z(),
+ tex_coord: Vector2 { x: u, y: v },
+ });
+ }
+ }
+ for y in 0..side - 1 {
+ for x in 0..side - 1 {
+ let a = u32::try_from(y * side + x).map_err(debug)?;
+ let c = a + u32::try_from(side).map_err(debug)?;
+ face.indices
+ .extend_from_slice(&[a, a + 1, c, a + 1, c + 1, c]);
+ }
+ }
+ model.faces.push(face);
+ model.create_asset(UUID::zero()).map_err(debug)?;
+ fs::write(root.join("mesh_asset.bin"), model.asset).map_err(|error| error.to_string())?;
+
+ let mut packet = AgentPausePacket::new_with_constructor().map_err(debug)?;
+ packet.agent_data.agent_id = UUID::new_with_string(config.uuid.clone()).map_err(debug)?;
+ packet.agent_data.session_id = UUID::new_with_u_int64(0x1234).map_err(debug)?;
+ packet.agent_data.serial_num = u32::try_from(config.packet_blocks).map_err(debug)?;
+ fs::write(
+ root.join("agent_pause.packet"),
+ packet.to_bytes_with_method().map_err(debug)?,
+ )
+ .map_err(|error| error.to_string())?;
+ write_manifest(root)
+}
+
+fn write_manifest(root: &Path) -> AppResult<()> {
+ let names = [
+ "workloads.json",
+ "notecard.txt",
+ "image.tga",
+ "mesh_asset.bin",
+ "agent_pause.packet",
+ ];
+ let mut hashes = BTreeMap::new();
+ for name in names {
+ hashes.insert(name.to_owned(), hash_file(&root.join(name))?);
+ }
+ write_json(&root.join("manifest.json"), &hashes)
+}
+
+fn context(root: &Path) -> AppResult {
+ let fixture = fixture(&root.join("workloads.json"))?;
+ let uuid = UUID::new_with_string(fixture.uuid.clone()).map_err(debug)?;
+ let llsd = OSD::Map(HashMap::from([
+ ("agent_id".into(), OSD::UUID(uuid)),
+ ("name".into(), OSD::String("MetaCrate benchmark".into())),
+ ("active".into(), OSD::Boolean(true)),
+ ("score".into(), OSD::Real(42.25)),
+ (
+ "items".into(),
+ OSD::Array(
+ (0..fixture.llsd_array_length)
+ .map(|value| OSD::Integer(i32::try_from(value).unwrap_or(i32::MAX)))
+ .collect(),
+ ),
+ ),
+ ]));
+ Ok(Context {
+ fixture,
+ uuid,
+ llsd,
+ packet: read(root, "agent_pause.packet")?,
+ notecard: read(root, "notecard.txt")?,
+ image: read(root, "image.tga")?,
+ mesh: read(root, "mesh_asset.bin")?,
+ })
+}
+
+fn read(root: &Path, name: &str) -> AppResult> {
+ fs::read(root.join(name)).map_err(|error| format!("read {name}: {error}"))
+}
+
+fn run_benchmarks(root: &Path) -> AppResult {
+ verify_manifest(root)?;
+ let context = context(root)?;
+ let mut results = Vec::new();
+ for workload in workloads() {
+ let iterations = (workload.iterations)(&context.fixture);
+ let cold = measure(&context, workload.run, 1)?;
+ let warmup = (iterations / context.fixture.warmup_divisor).max(1);
+ black_box((workload.run)(&context, warmup)?);
+ let mut warm_samples = Vec::with_capacity(RUNS);
+ for _ in 0..RUNS {
+ warm_samples.push(measure(&context, workload.run, iterations)?);
+ }
+ let mut ordered = warm_samples.clone();
+ ordered.sort_by_key(|sample| sample.elapsed_ns);
+ let warm_median = ordered[RUNS / 2].clone();
+ results.push(BenchmarkResult {
+ name: workload.name.into(),
+ category: workload.category.into(),
+ unit: "operation".into(),
+ fixture: workload.fixture.into(),
+ cold,
+ warm_samples,
+ warm_median,
+ });
+ }
+ Ok(Report {
+ schema: TOOL_SCHEMA,
+ runtime: "rust-native".into(),
+ reference_commit: context.fixture.reference_commit.clone(),
+ fixture_hashes: manifest(root)?,
+ environment: Environment {
+ os: std::env::consts::OS.into(),
+ arch: std::env::consts::ARCH.into(),
+ logical_cpus: std::thread::available_parallelism().map_or(1, usize::from),
+ toolchain: command_version("rustc", &["--version"]),
+ profile: "benchmark (opt-level=1, debug=0, incremental=false)".into(),
+ },
+ results,
+ })
+}
+
+fn measure(
+ context: &Context,
+ function: fn(&Context, usize) -> AppResult,
+ iterations: usize,
+) -> AppResult {
+ let region = Region::new(ALLOCATOR);
+ let started = Instant::now();
+ black_box(function(context, iterations)?);
+ let elapsed = started.elapsed();
+ let stats = region.change();
+ Ok(metrics(iterations, elapsed.as_nanos(), stats))
+}
+
+fn metrics(iterations: usize, elapsed_ns: u128, stats: Stats) -> Metrics {
+ let seconds = elapsed_ns as f64 / 1_000_000_000.0;
+ let retained = stats.bytes_allocated as i128 - stats.bytes_deallocated as i128
+ + stats.bytes_reallocated as i128;
+ Metrics {
+ iterations,
+ elapsed_ns,
+ latency_ns: elapsed_ns as f64 / iterations as f64,
+ throughput_per_second: iterations as f64 / seconds,
+ allocations: Some(stats.allocations + stats.reallocations),
+ bytes_allocated: stats.bytes_allocated,
+ retained_bytes: retained,
+ }
+}
+
+fn workloads() -> [Workload; 14] {
+ [
+ Workload {
+ name: "uuid_math",
+ category: "uuid/math",
+ fixture: "workloads.json",
+ iterations: |f| f.uuid_math_iterations,
+ run: uuid_math,
+ },
+ Workload {
+ name: "llsd_xml",
+ category: "LLSD",
+ fixture: "workloads.json",
+ iterations: |f| f.llsd_iterations,
+ run: llsd_xml,
+ },
+ Workload {
+ name: "llsd_json",
+ category: "LLSD",
+ fixture: "workloads.json",
+ iterations: |f| f.llsd_iterations,
+ run: llsd_json,
+ },
+ Workload {
+ name: "llsd_binary",
+ category: "LLSD",
+ fixture: "workloads.json",
+ iterations: |f| f.llsd_iterations,
+ run: llsd_binary,
+ },
+ Workload {
+ name: "llsd_notation",
+ category: "LLSD",
+ fixture: "workloads.json",
+ iterations: |f| f.llsd_iterations,
+ run: llsd_notation,
+ },
+ Workload {
+ name: "llsd_protobuf",
+ category: "LLSD",
+ fixture: "workloads.json",
+ iterations: |f| f.llsd_iterations,
+ run: llsd_protobuf,
+ },
+ Workload {
+ name: "packet_codec",
+ category: "packet codec",
+ fixture: "agent_pause.packet",
+ iterations: |f| f.packet_iterations,
+ run: packet_codec,
+ },
+ Workload {
+ name: "asset_decode",
+ category: "asset decode",
+ fixture: "notecard.txt",
+ iterations: |f| f.asset_iterations,
+ run: asset_decode,
+ },
+ Workload {
+ name: "image_decode",
+ category: "image decode",
+ fixture: "image.tga",
+ iterations: |f| f.image_iterations,
+ run: image_decode,
+ },
+ Workload {
+ name: "mesh_decode",
+ category: "mesh decode",
+ fixture: "mesh_asset.bin",
+ iterations: |f| f.mesh_iterations,
+ run: mesh_decode,
+ },
+ Workload {
+ name: "inventory_update",
+ category: "inventory update",
+ fixture: "workloads.json",
+ iterations: |f| f.inventory_iterations,
+ run: inventory_update,
+ },
+ Workload {
+ name: "object_update",
+ category: "object update",
+ fixture: "workloads.json",
+ iterations: |f| f.object_iterations,
+ run: object_update,
+ },
+ Workload {
+ name: "rendering",
+ category: "rendering",
+ fixture: "workloads.json",
+ iterations: |f| f.rendering_iterations,
+ run: rendering,
+ },
+ Workload {
+ name: "client_throughput",
+ category: "client throughput",
+ fixture: "workloads.json",
+ iterations: |f| f.client_iterations,
+ run: client_throughput,
+ },
+ ]
+}
+
+fn uuid_math(context: &Context, iterations: usize) -> AppResult {
+ let rotation =
+ Quaternion::create_from_eulers_with_single_single_single(0.25, 0.5, 0.75).map_err(debug)?;
+ let mut matrix = Matrix4::create_translation(Vector3 {
+ x: 10.0,
+ y: 20.0,
+ z: 30.0,
+ })
+ .map_err(debug)?;
+ let mut checksum = 0_u64;
+ for index in 0..iterations {
+ let parsed = UUID::new_with_string(context.fixture.uuid.clone()).map_err(debug)?;
+ matrix = Matrix4::transform(matrix, rotation).map_err(debug)?;
+ checksum ^=
+ parsed.get_u_long().map_err(debug)? ^ matrix.m41.to_bits() as u64 ^ index as u64;
+ }
+ Ok(checksum)
+}
+
+macro_rules! llsd_workload {
+ ($name:ident, $serialize:expr, $deserialize:expr) => {
+ fn $name(context: &Context, iterations: usize) -> AppResult {
+ let mut checksum = 0_u64;
+ for _ in 0..iterations {
+ let encoded = $serialize(&context.llsd).map_err(debug)?;
+ let decoded = $deserialize(encoded).map_err(debug)?;
+ checksum ^= u64::from(decoded.as_boolean().map_err(debug)?);
+ }
+ Ok(checksum)
+ }
+ };
+}
+
+llsd_workload!(
+ llsd_xml,
+ |value: &OSD| OSDParser::serialize_llsd_xml_bytes(value.clone()),
+ |bytes| OSDParser::deserialize_llsd_xml_with_bytes(bytes)
+);
+llsd_workload!(
+ llsd_binary,
+ |value: &OSD| OSDParser::serialize_llsd_binary_with_osd(value.clone()),
+ |bytes| OSDParser::deserialize_llsd_binary_with_bytes(bytes)
+);
+llsd_workload!(
+ llsd_protobuf,
+ |value: &OSD| OSDParser::serialize_llsd_protobuf(value.clone(), Some(true)),
+ |bytes| OSDParser::deserialize_llsd_protobuf_with_bytes(bytes)
+);
+
+fn llsd_json(context: &Context, iterations: usize) -> AppResult {
+ let mut checksum = 0;
+ for _ in 0..iterations {
+ let encoded =
+ OSDParser::serialize_json_string(context.llsd.clone(), None).map_err(debug)?;
+ let decoded = OSDParser::deserialize_json_with_string(encoded.clone()).map_err(debug)?;
+ checksum ^= encoded.len() as u64 ^ u64::from(decoded.as_boolean().map_err(debug)?);
+ }
+ Ok(checksum)
+}
+
+fn llsd_notation(context: &Context, iterations: usize) -> AppResult {
+ let mut checksum = 0;
+ for _ in 0..iterations {
+ let encoded = OSDParser::serialize_llsd_notation(context.llsd.clone()).map_err(debug)?;
+ let decoded =
+ OSDParser::deserialize_llsd_notation_with_string(encoded.clone()).map_err(debug)?;
+ checksum ^= encoded.len() as u64 ^ u64::from(decoded.as_boolean().map_err(debug)?);
+ }
+ Ok(checksum)
+}
+
+fn packet_codec(context: &Context, iterations: usize) -> AppResult {
+ let mut checksum = 0;
+ for _ in 0..iterations {
+ let mut start = 0;
+ let packet = AgentPausePacket::new_with_bytes_int32(context.packet.clone(), &mut start)
+ .map_err(debug)?;
+ let encoded = packet.to_bytes_with_method().map_err(debug)?;
+ checksum ^= encoded.len() as u64 ^ u64::from(packet.agent_data.serial_num);
+ }
+ Ok(checksum)
+}
+
+fn asset_decode(context: &Context, iterations: usize) -> AppResult {
+ let mut checksum = 0;
+ for _ in 0..iterations {
+ let asset = AssetNotecard::new_with_uuid_bytes(context.uuid, context.notecard.clone())
+ .map_err(debug)?;
+ if !asset.decode().map_err(debug)? {
+ return Err("notecard decode returned false".into());
+ }
+ checksum ^= asset.body_text.len() as u64;
+ }
+ Ok(checksum)
+}
+
+fn image_decode(context: &Context, iterations: usize) -> AppResult {
+ let mut checksum = 0;
+ for _ in 0..iterations {
+ let image = Targa::decode_to_managed_image_with_bytes(&context.image).map_err(debug)?;
+ checksum ^= image.red.len() as u64;
+ }
+ Ok(checksum)
+}
+
+fn mesh_decode(context: &Context, iterations: usize) -> AppResult {
+ let renderer = MeshFoundry::new().map_err(debug)?;
+ let mut checksum = 0;
+ for _ in 0..iterations {
+ let mesh = renderer
+ .generate_faceted_mesh_mesh_with_primitive_bytes_detail_level(
+ Primitive::new_with_constructor().map_err(debug)?,
+ context.mesh.clone(),
+ DetailLevel::Highest,
+ )
+ .map_err(debug)?
+ .ok_or_else(|| "mesh fixture returned no geometry".to_owned())?;
+ checksum ^= mesh
+ .faces
+ .iter()
+ .map(|face| face.vertices.len() + face.indices.len())
+ .sum::() as u64;
+ }
+ Ok(checksum)
+}
+
+fn inventory_update(context: &Context, iterations: usize) -> AppResult {
+ let store = Inventory::new_with_grid_client_uuid(
+ Arc::new(GridClient::new().map_err(debug)?),
+ context.uuid,
+ )
+ .map_err(debug)?;
+ for index in 0..iterations {
+ let id = UUID::new_with_u_int64((index % context.fixture.inventory_items) as u64 + 1)
+ .map_err(debug)?;
+ let mut item = InventoryItem::new_with_uuid(id).map_err(debug)?;
+ item.base.set_name(format!("item-{index}"));
+ store.update_node_for(&item).map_err(debug)?;
+ }
+ Ok(u64::try_from(store.count()).map_err(debug)?)
+}
+
+fn object_update(context: &Context, iterations: usize) -> AppResult {
+ let mut objects = (0..context.fixture.object_count)
+ .map(|index| {
+ let mut primitive = Primitive::new_with_constructor().expect("bounded primitive");
+ primitive.local_id = u32::try_from(index).unwrap_or(u32::MAX);
+ primitive
+ })
+ .collect::>();
+ let mut checksum = 0;
+ let object_count = objects.len();
+ for index in 0..iterations {
+ let object = &mut objects[index % object_count];
+ object.position = Vector3 {
+ x: index as f32,
+ y: (index & 255) as f32,
+ z: 21.0,
+ };
+ object.rotation = Quaternion::create_from_axis_angle_with_vector3_single(
+ Vector3::unit_z(),
+ (index & 255) as f32 / 255.0,
+ )
+ .map_err(debug)?;
+ checksum ^= u64::from(object.local_id) ^ u64::from(object.position.x.to_bits());
+ }
+ Ok(checksum)
+}
+
+fn rendering(_context: &Context, iterations: usize) -> AppResult {
+ let renderer = SimpleRenderer::new().map_err(debug)?;
+ let mut checksum = 0;
+ for _ in 0..iterations {
+ let mesh = renderer
+ .generate_faceted_mesh(box_primitive()?, DetailLevel::High)
+ .map_err(debug)?;
+ checksum ^= mesh
+ .faces
+ .iter()
+ .map(|face| face.indices.len())
+ .sum::() as u64;
+ }
+ Ok(checksum)
+}
+
+fn box_primitive() -> AppResult {
+ let mut primitive = Primitive::new_with_constructor().map_err(debug)?;
+ let mut data = PrimitiveConstructionData::new_with_constructor().map_err(debug)?;
+ data.p_code = PCode::Prim;
+ data.path_curve = PathCurve::Line;
+ data.set_profile_curve_with_property(ProfileCurve::Square);
+ data.path_scale_x = 1.0;
+ data.path_scale_y = 1.0;
+ data.path_begin = 0.0;
+ data.path_end = 1.0;
+ data.profile_begin = 0.0;
+ data.profile_end = 1.0;
+ data.profile_hollow = 0.0;
+ data.set_profile_hole(HoleType::Same);
+ data.path_revolutions = 1.0;
+ primitive.prim_data = data;
+ Ok(primitive)
+}
+
+fn client_throughput(context: &Context, iterations: usize) -> AppResult {
+ let _client = GridClient::new().map_err(debug)?;
+ let mut checksum = 0;
+ for index in 0..iterations {
+ for _ in 0..context.fixture.client_batch {
+ let mut source = RemoteParcelRequestReply::new().map_err(debug)?;
+ source.parcel_id = context.uuid;
+ let map = source.serialize().map_err(debug)?;
+ let mut target = RemoteParcelRequestReply::new().map_err(debug)?;
+ target.deserialize(map).map_err(debug)?;
+ checksum ^= target.parcel_id.get_u_long().map_err(debug)? ^ index as u64;
+ }
+ }
+ Ok(checksum)
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+struct ComparisonRow {
+ name: String,
+ rust_latency_ns: f64,
+ reference_latency_ns: f64,
+ latency_ratio: f64,
+ rust_bytes_per_operation: f64,
+ reference_bytes_per_operation: f64,
+ allocation_ratio: f64,
+ accepted: bool,
+ criterion: String,
+}
+
+#[derive(Debug, PartialEq, Serialize, Deserialize)]
+struct Comparison {
+ schema: u32,
+ reference_commit: String,
+ fixture_hashes: BTreeMap,
+ criteria: Criteria,
+ results: Vec,
+ accepted: bool,
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+struct Criteria {
+ maximum_latency_ratio: f64,
+ maximum_allocation_ratio: f64,
+ material_latency_regression_ratio: f64,
+ minimum_reference_latency_ns: f64,
+ reviewed_exceptions: Vec,
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+struct ReviewedException {
+ workload: String,
+ maximum_latency_ratio: f64,
+ maximum_allocation_ratio: f64,
+ rationale: String,
+}
+
+fn criteria() -> Criteria {
+ serde_json::from_str(include_str!("../../../benchmarks/release-criteria.json"))
+ .expect("committed release criteria must be valid")
+}
+
+fn compare_reports(rust_path: &Path, reference_path: &Path, output: &Path) -> AppResult<()> {
+ let rust: Report = read_json(rust_path)?;
+ let reference: Report = read_json(reference_path)?;
+ validate_pair(&rust, &reference)?;
+ write_json(output, &build_comparison(&rust, &reference)?)
+}
+
+fn build_comparison(rust: &Report, reference: &Report) -> AppResult {
+ let policy = criteria();
+ let mut rows = Vec::new();
+ for rust_result in &rust.results {
+ let reference_result = reference
+ .results
+ .iter()
+ .find(|result| result.name == rust_result.name)
+ .ok_or_else(|| format!("reference report is missing {}", rust_result.name))?;
+ let latency_ratio =
+ rust_result.warm_median.latency_ns / reference_result.warm_median.latency_ns;
+ let rust_bytes = rust_result.warm_median.bytes_allocated as f64
+ / rust_result.warm_median.iterations as f64;
+ let reference_bytes = reference_result.warm_median.bytes_allocated as f64
+ / reference_result.warm_median.iterations as f64;
+ let allocation_ratio = if reference_bytes == 0.0 {
+ if rust_bytes == 0.0 {
+ 1.0
+ } else {
+ f64::INFINITY
+ }
+ } else {
+ rust_bytes / reference_bytes
+ };
+ let exception = policy
+ .reviewed_exceptions
+ .iter()
+ .find(|exception| exception.workload == rust_result.name);
+ let maximum_latency = exception.map_or(policy.maximum_latency_ratio, |value| {
+ value.maximum_latency_ratio
+ });
+ let maximum_allocation = exception.map_or(policy.maximum_allocation_ratio, |value| {
+ value.maximum_allocation_ratio
+ });
+ let latency_noise_exempt =
+ reference_result.warm_median.latency_ns < policy.minimum_reference_latency_ns;
+ let material_latency_ok = latency_noise_exempt
+ || latency_ratio <= policy.material_latency_regression_ratio
+ || exception.is_some();
+ let latency_ok =
+ (latency_noise_exempt || latency_ratio <= maximum_latency) && material_latency_ok;
+ let allocation_ok = allocation_ratio <= maximum_allocation;
+ rows.push(ComparisonRow {
+ name: rust_result.name.clone(),
+ rust_latency_ns: rust_result.warm_median.latency_ns,
+ reference_latency_ns: reference_result.warm_median.latency_ns,
+ latency_ratio,
+ rust_bytes_per_operation: rust_bytes,
+ reference_bytes_per_operation: reference_bytes,
+ allocation_ratio,
+ accepted: latency_ok && allocation_ok,
+ criterion: if latency_ok && allocation_ok {
+ exception.map_or_else(
+ || "within default release thresholds".into(),
+ |value| format!("reviewed exception: {}", value.rationale),
+ )
+ } else {
+ "material regression requires profiling evidence or an explicit reviewed exception"
+ .into()
+ },
+ });
+ }
+ let accepted = rows.iter().all(|row| row.accepted);
+ Ok(Comparison {
+ schema: TOOL_SCHEMA,
+ reference_commit: rust.reference_commit.clone(),
+ fixture_hashes: rust.fixture_hashes.clone(),
+ criteria: policy,
+ results: rows,
+ accepted,
+ })
+}
+
+fn audit(
+ root: &Path,
+ rust_path: &Path,
+ reference_path: &Path,
+ comparison_path: &Path,
+) -> AppResult<()> {
+ verify_manifest(root)?;
+ let rust: Report = read_json(rust_path)?;
+ let reference: Report = read_json(reference_path)?;
+ let comparison: Comparison = read_json(comparison_path)?;
+ validate_pair(&rust, &reference)?;
+ let hashes = manifest(root)?;
+ if rust.fixture_hashes != hashes
+ || reference.fixture_hashes != hashes
+ || comparison.fixture_hashes != hashes
+ {
+ return Err("one or more reports do not match the committed fixture hashes".into());
+ }
+ let expected: Vec<_> = workloads().iter().map(|workload| workload.name).collect();
+ let expected_set = expected.iter().copied().collect::>();
+ for report in [&rust, &reference] {
+ if report.schema != TOOL_SCHEMA || report.reference_commit != EXPECTED_REFERENCE {
+ return Err("invalid report schema or reference commit".into());
+ }
+ let reported = report
+ .results
+ .iter()
+ .map(|result| result.name.as_str())
+ .collect::>();
+ if report.results.len() != expected.len() || reported != expected_set {
+ return Err(format!(
+ "{} report contains missing, duplicate, or unexpected workloads",
+ report.runtime
+ ));
+ }
+ for name in &expected {
+ let result = report
+ .results
+ .iter()
+ .find(|result| result.name == *name)
+ .ok_or_else(|| format!("{} report missing {name}", report.runtime))?;
+ if result.cold.iterations != 1
+ || result.warm_samples.len() != RUNS
+ || result.warm_median.iterations == 0
+ {
+ return Err(format!("{} has incomplete cold/warm evidence", result.name));
+ }
+ }
+ }
+ let recomputed = build_comparison(&rust, &reference)?;
+ let checked_bytes = fs::read(comparison_path)
+ .map_err(|error| format!("read {}: {error}", comparison_path.display()))?;
+ if checked_bytes != json_bytes(&recomputed)? {
+ return Err("release comparison is stale; rerun the compare command".into());
+ }
+ if !comparison.accepted {
+ return Err("release comparison is incomplete or contains an unaccepted regression".into());
+ }
+ println!(
+ "performance audit passed: {} workloads, pinned reference {}, fixture hashes verified",
+ expected.len(),
+ EXPECTED_REFERENCE
+ );
+ Ok(())
+}
+
+fn validate_pair(rust: &Report, reference: &Report) -> AppResult<()> {
+ if rust.runtime != "rust-native" || reference.runtime != "dotnet-reference" {
+ return Err(
+ "reports must be generated independently by rust-native and dotnet-reference".into(),
+ );
+ }
+ if rust.reference_commit != EXPECTED_REFERENCE
+ || reference.reference_commit != EXPECTED_REFERENCE
+ || rust.fixture_hashes != reference.fixture_hashes
+ {
+ return Err("reports use different fixtures or reference commits".into());
+ }
+ if rust.environment.os != reference.environment.os
+ || rust.environment.arch != reference.environment.arch
+ {
+ return Err("reports must be captured on the same OS and architecture".into());
+ }
+ Ok(())
+}
+
+fn verify_manifest(root: &Path) -> AppResult<()> {
+ let expected = manifest(root)?;
+ for (name, hash) in expected {
+ let actual = hash_file(&root.join(&name))?;
+ if actual != hash {
+ return Err(format!("fixture hash mismatch for {name}"));
+ }
+ }
+ Ok(())
+}
+
+fn manifest(root: &Path) -> AppResult> {
+ read_json(&root.join("manifest.json"))
+}
+
+fn hash_file(path: &Path) -> AppResult {
+ let bytes = fs::read(path).map_err(|error| format!("read {}: {error}", path.display()))?;
+ Ok(Sha256::digest(bytes)
+ .iter()
+ .map(|byte| format!("{byte:02x}"))
+ .collect())
+}
+
+fn read_json Deserialize<'de>>(path: &Path) -> AppResult {
+ serde_json::from_slice(
+ &fs::read(path).map_err(|error| format!("read {}: {error}", path.display()))?,
+ )
+ .map_err(|error| format!("parse {}: {error}", path.display()))
+}
+
+fn write_json(path: &Path, value: &T) -> AppResult<()> {
+ if let Some(parent) = path.parent() {
+ fs::create_dir_all(parent).map_err(|error| error.to_string())?;
+ }
+ fs::write(path, json_bytes(value)?)
+ .map_err(|error| format!("write {}: {error}", path.display()))
+}
+
+fn json_bytes(value: &T) -> AppResult> {
+ let mut bytes = serde_json::to_vec_pretty(value).map_err(|error| error.to_string())?;
+ bytes.push(b'\n');
+ Ok(bytes)
+}
+
+fn command_version(program: &str, args: &[&str]) -> String {
+ std::process::Command::new(program)
+ .args(args)
+ .output()
+ .ok()
+ .filter(|output| output.status.success())
+ .map_or_else(
+ || "unavailable".into(),
+ |output| String::from_utf8_lossy(&output.stdout).trim().into(),
+ )
+}
+
+fn debug(error: impl std::fmt::Debug) -> String {
+ format!("{error:?}")
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn workload_set_covers_every_issue_category() {
+ let categories: Vec<_> = workloads()
+ .iter()
+ .map(|workload| workload.category)
+ .collect();
+ for expected in [
+ "uuid/math",
+ "LLSD",
+ "packet codec",
+ "asset decode",
+ "image decode",
+ "mesh decode",
+ "inventory update",
+ "object update",
+ "rendering",
+ "client throughput",
+ ] {
+ assert!(categories.contains(&expected), "missing {expected}");
+ }
+ }
+
+ #[test]
+ fn metrics_separate_latency_throughput_allocations_and_retained_memory() {
+ let result = metrics(
+ 10,
+ 1_000,
+ Stats {
+ allocations: 2,
+ deallocations: 1,
+ reallocations: 1,
+ bytes_allocated: 100,
+ bytes_deallocated: 40,
+ bytes_reallocated: 20,
+ },
+ );
+ assert_eq!(result.latency_ns, 100.0);
+ assert_eq!(result.throughput_per_second, 10_000_000.0);
+ assert_eq!(result.allocations, Some(3));
+ assert_eq!(result.retained_bytes, 80);
+ }
+
+ #[test]
+ fn release_criteria_identify_material_regressions() {
+ let policy = criteria();
+ assert_eq!(policy.maximum_latency_ratio, 2.0);
+ assert!(policy.material_latency_regression_ratio < policy.maximum_latency_ratio);
+ assert_eq!(policy.reviewed_exceptions.len(), 3);
+ assert!(
+ policy
+ .reviewed_exceptions
+ .iter()
+ .any(|exception| exception.workload == "client_throughput")
+ );
+ }
+}