Skip to content

Make resolver GetTypeInfo methods return new instances on every call #76683

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

Closed
wants to merge 1 commit into from

Conversation

layomia
Copy link
Contributor

@layomia layomia commented Oct 5, 2022

Fixes #76535.

@layomia layomia added this to the 7.0.0 milestone Oct 5, 2022
@layomia layomia requested a review from krwq October 5, 2022 20:15
@layomia layomia self-assigned this Oct 5, 2022
@layomia layomia requested a review from eiriktsarpalis October 5, 2022 20:15
@ghost
Copy link

ghost commented Oct 5, 2022

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes #76535.

Author: layomia
Assignees: layomia
Labels:

area-System.Text.Json

Milestone: 7.0.0


HashSet<TypeGenerationSpec> types = new(_currentContext.TypesWithMetadataGenerated);
public override {JsonTypeInfoTypeRef} {GetTypeInfoMethodName}({TypeTypeRef} {TypeLocalVariableName})
=> {GetTypeInfoCoreMethodName}({TypeLocalVariableName}, {OptionsInstanceVariableName});
Copy link
Member

Choose a reason for hiding this comment

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

Nit:

Suggested change
=> {GetTypeInfoCoreMethodName}({TypeLocalVariableName}, {OptionsInstanceVariableName});
=> {GetTypeInfoCoreMethodName}({TypeLocalVariableName}, {OptionsPropertyName});

Copy link
Member

@eiriktsarpalis eiriktsarpalis left a comment

Choose a reason for hiding this comment

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

This is a good change overall, but it will introduce susbtantial performance regressions in all serialization methods accepting JsonSerializerContext (since metadata will be created from scratch on each operation).

Possible alternatives:

  1. Take Ensure source generated metadata properties are read-only. #76540 instead so that JsonSerializerContext.GetTypeInfo returns the same instances but guarantee that those are read-only. Note that IJsonTypeInfoResolver would still return fresh mutable instances to guarantee compositionality.
  2. Update the implementation of JsonSerializers's JsonSerializerContext resolution logic so that metadata is looked up via the JsonSerializerOptions cache. Note that the standard JsonSerializerOptions.GetTypeInfo* methods will return NotSupportedException on missing metadata instead of InvalidOperationException so some adjustment might be required there.

@eiriktsarpalis
Copy link
Member

Update the implementation of JsonSerializers's JsonSerializerContext resolution logic so that metadata is looked up via the JsonSerializerOptions cache.

On that note, it appears that this approach has the potential of interacting with the reflection fallback compatibility switch that was recently added. TL;DR if the compatibility switch is enabled, it would most likely result in reflection metadata leaking into JsonSerializerContext serialization methods -- a regression from .NET 6.

@eiriktsarpalis
Copy link
Member

eiriktsarpalis commented Oct 6, 2022

@layomia I pushed commit eiriktsarpalis@240a24c in my fork of your PR branch which demonstrate how we could keep using cached metadata in the JsonSerializerContext serialization overloads without regressing any functional tests. PTAL and incorporate in your PR as necessary.

@layomia
Copy link
Contributor Author

layomia commented Oct 6, 2022

On that note, it appears that this approach has the potential of interacting with the #75615 that was recently added. TL;DR if the compatibility switch is enabled, it would most likely result in reflection metadata leaking into JsonSerializerContext serialization methods -- a regression from .NET 6.

Yeah can confirm this happens; I noticed reflection-fallback test failures in an earlier iteration of this PR when taking this approach.

@layomia I pushed commit eiriktsarpalis@240a24c in my fork of your PR branch which demonstrate how we could keep using cached metadata in the JsonSerializerContext serialization overloads without regressing any functional tests. PTAL and incorporate in your PR as necessary.

I agree this would be the right way to mitigate the performance hit from this change were we to go down the path this PR proposes. But the solution in #76540 is more complete and less breaking so I'll close this in favor of that approach.

@layomia layomia closed this Oct 6, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Nov 5, 2022
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.

Contract metadata cached by the source generator are user-modifiable.
2 participants