Open
Conversation
Contributor
|
Unfortunately, considering my current workload I can't make it. |
Contributor
Author
|
I've found a very helpful article by Sasha Goldshtein here. Given 3 different types of deserializer methods: // Option 1 - using marshaller
public static T MarshallerSerializer<T>(byte[] data) where T : struct
{
var gch = GCHandle.Alloc(data, GCHandleType.Pinned);
try
{
return (T) Marshal.PtrToStructure(gch.AddrOfPinnedObject(), typeof(T));
}
finally
{
gch.Free();
}
}
// Option 2 - casting to ptr to generic struct
public static T PtrCastSerializer<T>(byte[] data) where T : struct
{
unsafe
{
fixed (byte* p = &data[0])
{
return (T)Marshal.PtrToStructure(new IntPtr(p), typeof(T));
}
}
}
// Option 3 - direct casting from byte array to struct (non-generic)
public static A DirectPtrSerializer(byte[] data)
{
unsafe
{
fixed (byte* packet = &data[0])
{
return *(A*) packet;
}
}
}, for test struct with 3 readonly int fields. The results are: BenchmarkDotNet=v0.10.1, OS=Microsoft Windows NT 6.2.9200.0
Processor=Intel(R) Core(TM) i5-6300HQ CPU 2.30GHz, ProcessorCount=4
Frequency=2250001 Hz, Resolution=444.4442 ns, Timer=TSC
[Host] : Clr 4.0.30319.42000, 32bit LegacyJIT-v4.6.1586.0
DefaultJob : Clr 4.0.30319.42000, 32bit LegacyJIT-v4.6.1586.0
This test only checks for deserialization process - 1st option is basically what this PR brings. 2nd option can be used over generic code and it's arund 50% faster. 3rd option is most interesting, but cannot be used over generic types - we need a code gen here. However I think, potential results may be worth of the effort: 123 times faster that the first option with no heap allocations! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Work in progress
This is a experimental serializer for structs that uses
Marshalclass for direct struct → byte array mapping instead of writing values field by field. Some initial benchmarks:New struct serializer is around 10% faster, which actually is a little disappointing. I'm probably missing something important here - maybe Marshal methods are slower than expected, or maybe this goal could be achieved by using different technique. @Scooletz would you like to review and give some tips?