- Notifications
You must be signed in to change notification settings - Fork5.2k
Fix JsonNode performance regression#104048
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
Tagging subscribers to this area: @dotnet/area-system-text-json,@gregsdennis |
| break; | ||
| default: | ||
| node=JsonValue.CreateFromElement(refelement,options); | ||
| node=newJsonValueOfElement(element,options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
The change looks good, but I'm a little surprised it caused such regressions. It looks like CreateFromElement is also using this constructor but before that is checking ValueKind against the same three cases above. Those branches were enough to cause significant regressions? This must be a super hot path?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
It's in the hot path for the lazy conversion ofJsonArray andJsonObject fromJsonElement backed to List and dictionary backed, which is what regressed by this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
I wonder if theref readonly parameter in the removed method contributed to the regression somehow.
andrewjsaidJun 26, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
My guess is that it callselement.ValueKind twice, which resolves as follows
publicJsonValueKindValueKind=> TokenType.ToValueKind();`
privateJsonTokenTypeTokenType=> _parent?.GetJsonTokenType(_idx)?? JsonTokenType.None
internalJsonTokenTypeGetJsonTokenType(intindex){CheckNotDisposed();return_parsedData.GetJsonTokenType(index);}
internalJsonTokenTypeGetJsonTokenType(intindex){AssertValidIndex(index);uintunion=MemoryMarshal.Read<uint>(_data.AsSpan(index+NumberOfRowsOffset));return(JsonTokenType)(union>>28);}
plus a small cost to run the switch statement ininternal static JsonValueKind ToValueKind(this JsonTokenType tokenType)
Which is quite a lot of indirection. Possibly changingCreateFromElement to create a localJsonValueKind kind = element.ValueKind; to avoid running the above twice? But still maybe running it once is even a lot here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Created a PR here#104108
Fixesdotnet/perf-autofiling-issues#36936 (comment)