Open buybackoff opened 6 years ago
I have implemented zero-copy deserialization from native memory here: https://github.com/Spreads/Utf8Json
I started this issue with serialization, but for my needs I need to know exact size before writing to native memory, so this issue as originally posted in not relevant so far.
I managed to improve deserialization speed by 2x. Cannot break down what change contributed, but from profiling work changes that are relevant to upstream:
SkipWS is called always, it's better to first check if the current symbol is what we are looking for (:
, ,
, etc) as if there is no white space, so aggressively betting on hot path. If we are unlucky, then check for WS. Use Vectorized check. Current check requires several ||
that are all false when not WS. Here is an example: https://github.com/Spreads/Utf8Json/blob/f53817e382c29bf77ca00a2b9abaa2842179063a/src/Utf8Json/JsonReader.cs#L275-L330
SpipWS could be merged with IsInRange. SpipWS returns bool, true if in range. Other methods cannot trip outside the buffer.
ReadInNull could be combined with SkipWS for the most common false case, also vectorized: https://github.com/Spreads/Utf8Json/blob/f53817e382c29bf77ca00a2b9abaa2842179063a/src/Utf8Json/JsonReader.cs#L332-L379
ReadIsEndObjectWithSkipValueSeparator is very hot, could add hot-path check: https://github.com/Spreads/Utf8Json/blob/f53817e382c29bf77ca00a2b9abaa2842179063a/src/Utf8Json/JsonReader.cs#L548-L554
IsDigit
check via (unchecked((uint)(bytes[i]-'0') <= 9))
is faster than two ifs.
All exception throwing should be in a separate method without arguments. Even a NoInlining
method that accepts a string
message prevents inlining.
For writes,
get_hasValue
is shown in profiler), Try(...out)
pattern is better.Span<byte>
overloads should be sufficient, as Memory<byte>
allows you to get a span of it.
Very valuable addition to avoid zero-copy would be API to serialize into
Span<byte>/Memory<byte>
. If there is not enough space - then return false. But the happy path for message of typical size is to get a largeSpan
, write to it, get written length and then slice the span for the next value.This is now blocking me to have zero-copy.
Desired API is:
Pseudo-code: