CPU: Intel i7-4770K @ 3.50Ghz
Windows 10, 64-bit
Vanilla
Safe .NET 3.5
Name Mean StdD Unit
Encode 1.082 0.349 us/op
Decode 0.018 0.039 us/op
Traverse 0.438 0.229 us/op
Unsafe .NET 3.5
Name Mean StdD Unit
Encode 0.916 0.326 us/op
Decode 0.010 0.030 us/op
Traverse 0.448 0.714 us/op
Change to CreateString
Safe .NET 3.5
Name Mean StdD Unit
Encode 1.000 0.347 us/op
Decode 0.014 0.035 us/op
Traverse 0.424 0.206 us/op
Unsafe .NET 3.5
Name Mean StdD Unit
Encode 0.872 0.366 us/op
Decode 0.018 0.039 us/op
Traverse 0.310 0.210 us/op
After Pad Optimization - changed the Pad method to loop inside the ByteBuffer, removing extra method calls. Only call Pad from Prep when there's a size.
Safe .NET 3.5
Name Mean StdD Unit
Encode 0.854 0.317 us/op
Decode 0.012 0.033 us/op
Traverse 0.390 0.198 us/op
Unsafe .NET 3.5
Name Mean StdD Unit
Encode 0.782 0.334 us/op
Decode 0.008 0.027 us/op
Traverse 0.306 0.239 us/op
A further experiment was to #define away the bounds checks in the ByteBuffer (AssertOffsetAndLength). This leads to a slight gain, mostly in the unsafe configuration. Obviously carried more risk in Unsafe.
Safe .NET 3.5
Name Mean StdD Unit
Encode 0.844 0.338 us/op
Decode 0.018 0.039 us/op
Traverse 0.392 0.246 us/op
Unsafe .NET 3.5
Name Mean StdD Unit
Encode 0.668 0.311 us/op
Decode 0.018 0.039 us/op
Traverse 0.242 0.214 us/op
Ran the Java Benchmark on the same machine (https://github.com/ennerf/flatbuffers-java-benchmark)
It looks like with the optimizations above, the C# version is roughly equivalent to the performance of Java version. Java Direct is slightly quicker than the Unsafe version of C# without my removal of the bounds checking.