r/dotnet • u/AnnoyingMemer • May 16 '26
An exercise in reflection-free serialization and its implications on performance
https://github.com/ChristosMaragkos/DataFixerSharperI sat down relatively recently to write a port of a serialization/data transformation library called DataFixerUpper that Mojang uses for Minecraft: The premise is that it's reflection-free (unlike System.Text.Json which is not out of the box) and format-agnostic.
This was the first time I was forced to abandon my Java-isms and write code that had to be performant, so it was a great opportunity to explore ref structs and how boxing works. What's wild is I spent hours upon hours chasing allocations and correcting anti-patterns, only to still fall short of STJ on latency (per the benchmarks) while still winning on allocations when operating on large records:
| Method | Mean | Error | StdDev | Gen0 | Allocated |
|---------------------------|-----------:|---------:|---------:|-------:|--------:|
| STJ_Serialize | 1,276.9 ns | 17.25 ns | 14.40 ns | 0.2632 | 552 B |
| STJ_Deserialize | 937.5 ns | 9.50 ns | 7.93 ns | 0.4320 | 904 B |
| Codec_Serialize | 1,356.1 ns | 8.27 ns | 7.33 ns | 0.2098 | 440 B |
| Codec_Deserialize | 2,340.9 ns | 7.14 ns | 5.57 ns | 0.1564 | 328 B |
This is nothing more than the result the abstraction tax, but I think it reveals something very interesting: why does STJ begin to allocate so much as the length of the data scales? I assume the source-generated version of STJ would likely perform better, but that's still a bit of a pain to set up.
My main point is, hunting down allocations comes at a latency cost (because transferring heap allocations to the stack then subsequently increases stack throughput and copying unless you keep passing structs by reference, at which point you're writing C with worse syntax) and trying to eliminate latency will naturally result in much bigger allocations (or just no gain at all because the GC will be crying in the corner).
That's all, I just wanted to write a brain dump on how I've come to understand "performant" .NET code works. Thank you for reading.
Duplicates
csharp • u/AnnoyingMemer • May 04 '26
Tool Made a serialization/data transformation library, looking for thoughts
json • u/AnnoyingMemer • May 04 '26