neuecc / Utf8Json

Definitely Fastest and Zero Allocation JSON Serializer for C#(NET, .NET Core, Unity, Xamarin).
MIT License
2.35k stars 266 forks source link

Serialize into Span<byte>/Memory<byte> #87

Open buybackoff opened 6 years ago

buybackoff commented 6 years ago

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 large Span , 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:

int JsonSerializer.Serialize(object item, Span<byte> span);
(returns negative value if there is not enough space in the span, or written size on success)

Pseudo-code:

Span<byte> span = GetSpan(large_enough_length_for_100s_items);
foreach(var item in items)
{
    var written = JsonSerializer.Serialize(item, span);
    if(written < 0)
    {
       // renew span 
       span = GetSpan(large_enough_length_for_100s_items); 
       written = JsonSerializer.Serialize(item, span);       
    } else {
      span = span.Slice(written);
    }
}
buybackoff commented 5 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:

For writes,

Timovzl commented 4 years ago

Span<byte> overloads should be sufficient, as Memory<byte> allows you to get a span of it.