Change 'in' modifier usage to 'ref' for performance#40114
Change 'in' modifier usage to 'ref' for performance#40114steveharter merged 4 commits intodotnet:masterfrom
Conversation
|
I'm not sure this is the right fix. Changing (That said, if you want to change these from |
Yes we do that in other places -- at least one other I'll look at changing the existing code and report back. However using |
I was able to change the DbRow to use in+readonly but not the serializer stack based struct. That is mutable and can't be made readonly. |
What methods are you calling that can't be made readonly? That suggests they actually mutate |
|
To be clear, I'm fine in general with a change to ref. But keep in mind that there are potential problems with it, too: the reason you get the defensive copy with in is because the target may mutate... if that protection was necessary and you change to ref, now you may have a functional problem. |
As mentioned it is currently error-prone to determine if a given method should use Since this in internal code, there is not a concern about accidently mutating state. Originally when the code was written I was not aware of the performance side-affect of It is unfortunate IMO that the defensive copy is done or needs to be done - a different approach would be to not allow at compile time calling a non-readonly field\property when |
Why not? If you use If you use |
This can be achieved with an analyzer. Someone just needs to write one. Maybe @jaredpar's team already has one or has one in the works? |
The one that we've been looking at using in our own code base is ErrorProne.NET: https://github.com/SergeyTeplyakov/ErrorProne.NET |
Perhaps we should modify every internal (and public?) struct to adorn with readonly modifers so consumers can properly use Once such as analyzer usage is pervasive (built-in or prescriptive in some way) then I think it is feasible to use |
An analyzer like ErrorProne.NET will tag such places and let you know when a defensive copy is being made. In general, I think using Hopefully we can get warning waves eventually and it can just be a compiler warning instead. |
But if a mutation does happen, it is silent, which is a likely bug. I added my thoughts at https://github.com/dotnet/corefx/issues/40166 |
|
/azp run corefx-ci |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
Committing this; there is likely future work to improve |
|
|
||
| try | ||
| { | ||
| Parse(utf8JsonSpan, reader, ref database, ref stack); |
There was a problem hiding this comment.
I think we should port this to 3.0, particularly passing a mutable struct by value here (the Utf8JsonReader). Aside from reducing the struct copy/perf benefit, it would be best if we reduce accidental pass-by-value code (to avoid false positives when looking for such instances in the future).
|
@tannergooding mentioned https://github.com/SergeyTeplyakov/ErrorProne.NET/blob/master/ReadMe.md..@stephentoub did you try that one? |
|
I tried it, but was not able to install the vsix in VS 2019 (and referencing the NuGet package didn't work within corefx libraries and I don't know why). Using the NuGet package in a standalone .NET Core 3.0 app worked as expected though. I have reached out to @SergeyTeplyakov to help fix the VSIX issue. |
Commit migrated from dotnet/corefx@46d3f57
Some minor optimizations to change
inmodifier toref. This reduces the generated code size for these cases.Pertains to https://github.com/dotnet/corefx/issues/39935 (doesn't "fix" as original issue was related to potential bugs).
For example with the code in [UnescapeString] ()
corefx/src/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs
Line 904 in 1841042
With
in:And with
ref: