Skip to content
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

Coreclr compatibility: Implemented Json.Net fallback serializer #1047

Merged
merged 1 commit into from Nov 26, 2015

Conversation

dVakulen
Copy link
Contributor

Related to #368.
Default fallback serializer is BinaryFormatter, using of the Json.Net one can be configured through boolean property "UseJsonFallbackSerializer".

@dVakulen dVakulen force-pushed the json-net-fallback-serializer branch 3 times, most recently from 987fb9d to 4bef196 Compare November 19, 2015 22:19
@@ -36,8 +37,8 @@ namespace Orleans.Providers.Streams.AzureQueue
internal class AzureQueueBatchContainer : IBatchContainer
{
private EventSequenceToken sequenceToken;
private readonly List<object> events;
private readonly Dictionary<string, object> requestContext;
public readonly List<object> events;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to be completely unmanagable.
If we want internal runtime types to be Json serializable, we need to find a better/robust/testable way to enforce that. Otherwise, it will keep breaking. Look at the 5 times we already broke the pub sub state json serialization, since we used the approach of marking fields public. There are much better alternatives.

I suggest to open a separate issue and discuss it. I am sure people in our community have better expertise how to make sure their internal types are json-able.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the way of fixing PubSubStateGrain was quite bad idea.

#if DNXCORE50
throw new OrleansException("Can't use binary formatter as fallback serializer while running on .Net Core");
#else
serializer = new BinaryFormatterSerializer();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does not seem like we need to allocate a new BinaryFormatterSerializer instance every time it is called, right? It is pretty much stateless, just a call through into Ser/Deser/Copy methods. So better allocate once and return, save some GC.
Same applies to OrleansJsonSerializer.
Serialization code is of course the most sensitive to perf, as it is on the hottest path.

@dVakulen
Copy link
Contributor Author

Updated. Made few more internal types json serialization friendly.

}

var numAgents = await mgmt.SendControlCommandToProvider(adapterType, adapterName, (int)PersistentStreamProviderCommand.GetNumberRunningAgents);
Assert.AreEqual(2, numAgents.Length);
int totalNumAgents = numAgents.Cast<int>().Sum();
int totalNumAgents = numAgents.Select(n=>int.Parse(n.ToString())).Sum();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove those n=>int.Parse(n.ToString().
We should not need to go via string.
If there is a problem with int to long, we can fix that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When serializing with binary formatter the resulting array contains ints and when with Json.Net one - longs.

@jason-bragg
Copy link
Contributor

"I ran all tests with json serializer, so that i found the issues with it. Yes, I'll add new tests."

At a quick glance, I'm seeing over a hundred Orleans classes marked [Serializable]. I'd like to believe they are all covered by tests, but I'm not that confident. I don't know any simple way to vet this change.

@dVakulen
Copy link
Contributor Author

BinaryFormatter still remains the default serializer, so this one should be pretty safe. I can remove ability to configure it so that users won't be able to use untested feature, and Json.Net will be used only when running on .Net Core and tested along the other specific to the coreclr changes.

@dVakulen
Copy link
Contributor Author

Commits squashed.

@dVakulen dVakulen force-pushed the json-net-fallback-serializer branch 3 times, most recently from 5790bac to b222230 Compare November 21, 2015 05:48
@dVakulen
Copy link
Contributor Author

Removed some allocations in the serialization code using thread local serializers instead of creation of the new ones on each serialization\deserialization, the number of GC collections of the zero gen on benchmark with deep copy of POCO decreased by ~7% but performance for binary serialization for some reason dropped by 15%. Will create separate PR for this later, if needed. Also, seems like Json.Net 2 - 3 times faster than binary formatter and causes lower GC pressure (2x less collections of the zero gen in comparison to the BinaryFormatter, 4x - first gen)

"Cann't use binary formatter as fallback serializer while running on .Net Core, will use Json.Net instead");
}

useJsonFallbackSerializer = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.useJsonFallbackSerializer = true, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, i replaced field useJsonFallbackSerializer with IExternalSerializer fallbackSerializer.

@gabikliot
Copy link
Contributor

OK, so I have a couple of comments:

  1. In MessagingConfiguration you also need to print the new property UseJsonFallbackSerializer
  2. ISerializer: does not feel like we really need a new interface ISerializer. Lets just use the same one IExternalSerializer and we can later rename the IExternalSerializer to ISerializer. And IsSupportedType can just return true in the fallback one.
  3. Lets try to minimize/standardize the way we integrate with Json on internal runtime types. So for example, for ActivationAddress and GuidId and UniqueIdentifier lets use the converter, like you did for IPAddress inside the JsonSerializer, instead of JsonProperty and JsonConstructor.
  4. AzureQueueBatchContainer can not be specified in the JsonSerializer, since it will create a dependancy on Azure dll, therefore using JsonProperty or ISerializable interface is OK.
  5. After all fixes, please rebase and squash into one commit.

I would like this PR to be accepted after #1052.

@sergeybykov sergeybykov added this to the vNext milestone Nov 25, 2015
@dVakulen
Copy link
Contributor Author

Updated & Squashed. Left JsonConstructor on ActivationAddress and JsonProperty in UniqueIdentifier because implementing converters for them would require too much seemingly unnecessary code compared to just adding attributes.

@gabikliot
Copy link
Contributor

Looks good. Going to merge.

There is still an open question if all our internal types are json-serializable or do we miss any.
There is a good chance we are indeed missing something, like @jason-bragg pointed above in his comment: #1047 (comment).
I agree with @dVakulen that BinaryFormatter still remains the default serializer, so this one should be pretty safe and for now only intended to be used with .Net Core. As we use more and more json, we will discover those gaps and fill them in.

gabikliot pushed a commit that referenced this pull request Nov 26, 2015
 Implemented Json.Net fallback serializer
@gabikliot gabikliot merged commit ae97c47 into dotnet:master Nov 26, 2015
@gabikliot
Copy link
Contributor

Thank you @dVakulen !

@gabikliot gabikliot modified the milestones: CoreCLR, vNext Nov 26, 2015
@sergeybykov
Copy link
Contributor

I planned to merge it post 1.1.0. That's why I assigned the vNext milestone to it.

@gabikliot
Copy link
Contributor

Ohhhh...
Sorry.
It was not clear to me. I thought we said we will mark it as On Hold, as we said before, with label or milestone. I did not understand what vNext meant - I thought it is like coreclr - vNextDotNet.

Anyway, I think this PR was safe. It added json as an alternative fallback serializer, but the binary serializer was still the default one, and it did not change.

@gabikliot gabikliot changed the title Implemented Json.Net fallback serializer Coreclr compatibility: Implemented Json.Net fallback serializer Nov 26, 2015
@dVakulen
Copy link
Contributor Author

@gabikliot Thank you for the review!

@dVakulen dVakulen deleted the json-net-fallback-serializer branch November 26, 2015 07:12
@gabikliot gabikliot modified the milestones: CoreCLR, v1.2.0 Dec 4, 2015
@github-actions github-actions bot locked and limited conversation to collaborators Dec 9, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants