-
-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Faster instance creation for ValuesJsonConverter #119
Faster instance creation for ValuesJsonConverter #119
Conversation
As far as deserialization goes, there are probably two more low-hanging fruit in the library:
|
I discovered the same thing some time ago. I also discovered that the generic https://github.com/Dotnet-Boxed/Framework/blob/master/Source/Boxed.Mapping/Factory.cs Very similar to yours. One difference is that instead of using a collection to store a map, we use a static instead. However, we can't always do this in our case because we have constructor parameters. I raised an issue in corefx at the time for |
I've moved the object activation code out to a separate class like you suggested and extended it a little to support custom parameter types (which will be useful for a future PR around faster single-item deserialization). |
Thanks for that. |
It turns out
Activator.CreateInstance
is slow relative to the rest of the serialization process.In that image, you can see it taking a little over 30% of the deserialization time.
Using a technique from JSON .NET (with a similar technique in System.Text.Json), the idea is to create a custom constructor delegate to avoid the overhead of finding and calling the constructor through reflection.
In this image, we can see the large drop in both the
System.Private.CoreLib
module as well as the line percentage dropping down to ~7% of the deserialization time.With benchmarks, we can see the difference in performance and allocations as well. Specifically with the Book benchmark:
Before
After
As you can see, deserialization times are cut in half while also allocating ~24% less.
The constructor delegate cache is built per each object type (eg.
OneOrMany<string>
orValues<string, Uri>
) with every type getting an entry. For a one-off serialization of a type, this would actually use more and likely take longer as each constructor gets generated for every type on every property being serialized. The benefits to this change come more with the frequency of deserializations.With the update to the benchmark runtime moniker, I found there to be a strange performance measuring issue when there is a mix of .NET 3.1 target in the project file with a runtime moniker targeting 3.0 while not having 3.0 installed (.NET Core was performing far worse than .NET Framework). I figure let's just make the project target and the benchmark runtime moniker be the same.