Newtonsoft.Json icon indicating copy to clipboard operation
Newtonsoft.Json copied to clipboard

Couldn't Newtonsoft.Json utilize System.Span for more performance?

Open taori opened this issue 6 years ago • 12 comments

https://blogs.msdn.microsoft.com/dotnet/2017/11/15/welcome-to-c-7-2-and-span/

Just wondering if altering Newtonsoft.Json to utilize that feature wouldn't result in a significant speedup, since working with strings is really the heavy lifting for Newtonsoft.Json too i would imagine?

taori avatar Jul 04 '18 22:07 taori

IMHO the announcement linked above is somewhat misleading, so hopefully people here won't mind if I add a few details about the current state of spans in .NET.

It is important to know that using spans would be an optimization that's currently only feasible on .NET Core ≥2.1 because, at this time, there is no other .NET platform that fully supports spans.

By "full support", I am referring to three separate requirements:

  1. Availability of the base types Span<T>, ReadOnlySpan<T>, Memory<T>, and ReadOnlyMemory<T>.

  2. Availability of APIs in the BCL that use the above types. (Without dedicated APIs, spans are about as useful as System.ArraySegment<T>—that is, not useful at all.)

  3. Recognition of the above types by the .NET runtime's JIT compiler for efficient code generation. (Only with runtime support are spans really as "fast" as plain array index or pointer operations. Without runtime support, they might even cause additional overhead.)

Concerning the .NET Framework, you can get (1) via the NuGet package System.Memory. But you might be out of luck regarding (2) and (3) as the classic .NET Framework will likely never have BCL nor JIT support for spans—see https://github.com/Microsoft/dotnet/issues/770.

Concerning .NET Standard, BCL support for spans is ~~apparently~~ planned for ~~vNext—see https://github.com/dotnet/standard/issues/682#issuecomment-401947585~~ .NET Standard 2.1.

This could be an indication that full span runtime support (3) might eventually make it into platforms other than .NET Core (most notably, Mono and Mono-based runtimes—see e.g. https://github.com/mono/mono/issues/7249).

I am also linking to https://github.com/Tornhoof/SpanJson for those who are interested in seeing spans at work in JSON parsing.

stakx avatar Jul 08 '18 11:07 stakx

@stakx so (3) indirectly states you should not use aspnetcore 2.1 on .NET Framework although being a valid target. I have not noticed a warning so far that it will be slower than aspnetcore 2.0 when not used on netcore.

springy76 avatar Jul 27 '18 08:07 springy76

@springy76, let's not get too sidetracked here, but... that is interesting. I am not familiar with ASP.NET Core, but assuming that 2.1 makes heavy use of spans, I cannot say how they were able to get it working on top of the .NET Framework. Not so much because of the missing JIT support (3), which would just make it slower, but because of missing BCL APIs (2), which would make it impossible to compile and run.

stakx avatar Jul 27 '18 09:07 stakx

Anything with span would wait until netstandard3.0 when the Span APIs are available.

JamesNK avatar Jul 27 '18 09:07 JamesNK

Spans are now planned for inclusion in .NET Standard 2.1.

stakx avatar Aug 30 '18 11:08 stakx

This blog post (and a comment underneath) seems to imply that .NET Framework 4.8 will have the JIT improvements for Span<T> and similar - though the additional Span<T> APIs (which would then only be available via System.Memory), and only for 64-bit: https://blogs.msdn.microsoft.com/dotnet/2018/09/17/announcing-net-framework-4-8-early-access-build-3646/

Runtime – JIT improvements The JIT in .NET 4.8 is based on .NET Core 2.1. All bug fixes and many code generation-based performance optimizations from .NET Core 2.1 are now available in the .NET Framework.

Russ Keldorph [MSFT] Only the 64-bit JIT will be based on .NET Core. The 32-bit JIT is not RyuJIT and will remain largely unchanged in .NET 4.8. Sorry for the confusion.

jmazouri avatar Jan 21 '19 20:01 jmazouri

Seeing a lot of libs use span and esp readonlymemory underneath eg MVC core , Redis etc .. they are all providing ReadOnlyspan , so to get bytes[] you have a toarray and the data is copied from the buffer to the heap .

bklooste avatar May 20 '20 23:05 bklooste

any updates? is it possible?

Marusyk avatar Dec 22 '20 10:12 Marusyk

@JamesNK

Anything with span would wait until netstandard3.0 when the Span APIs are available.

Span<T>. ref and ReadOnlySpan<T> Struct is available in netstandrad2.1 and .Net6 support Deserialize(ReadOnlySpan<Char>) here

It's nice if Newtonsoft.Json can support span.

moh-hassan avatar Jun 13 '22 06:06 moh-hassan

JsonReader is not a ref struct so it's not possible to rewrite JSON parsing to use span from the bottom up. For example, it's not possible to add a Deserialize method that takes a span because it can't be stored by JsonReader.

JamesNK avatar Jun 13 '22 06:06 JamesNK

@JamesNK Thanks for reply. Now it's clear :)

moh-hassan avatar Jun 13 '22 06:06 moh-hassan