-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Dictionary (etc) optimization suggestion, use readonly ref #24178
Comments
Modern calling conventions have this optimization built-in: Small value types are passed by value and large value types are passed by reference in the JIT code on x64 and arm64 today. |
If that is the case then what is the big gain of passing a struct by ref? Until now, I understood that value types pass by value and passing by ref is an optimization. I therefore suggested the above optimization since it is easy to implement with the new "in" feature as it doesn't effect call sites. |
Value types are logically passed by value. The low-level implementation implementation may be actually passing pointers to them around.
Passing by ref is primarily a semantic change - the function can modify the value passed in. The different performance characteristics are secondary effect.
The JIT follows the standard platform calling conventions. The exact rules differ from platform to platform. For example, https://docs.microsoft.com/en-us/cpp/build/parameter-passing describes how arguments are passed on Windows x64. The sentence relevant to this discussion is
You should measure and understand the performance effects of |
Nope because that would be a breaking change. Besides, passing things by ref is only (potentially) better for large value types. For reference types and small value types passing by ref is basically a de-optimization.
Yes but when they do pass a pointer around they first make a copy of the value being passed as a parameter and pass a pointer to that copy. Passing values by ref avoids that copy. |
The pros and cons of the new "in" parameter are much clearer now. |
It depends on what you mean by "Dictionary.Contains, TryGetValue etc. can all use "in" parameters as they only read from the input". To me it sounds as if you're suggesting to change the existing methods and that's a breaking change. An alternative is to add overloads (e.g. |
AFAIK, changing the implementation of Dictionary.Contains(T) to Dictionary.Contains(in T) would still work for the interface Dictionary.Contains(T), and therefore wouldn't be a breaking change. This of course assumes that the other aspects of the dictionary interface also can be assumed not to mutate the key, because abvously changing assumptions is a breaking change. |
What do you mean by changing the implementation? Changing from Dictionary.Contains(T) to Dictionary.Contains(in T) changes the API signature and is a breaking change. |
Yes, it looks like there is some confusion about what But of course, in IL/metadata |
That is exactly what I missed. Thanks for clarifying. |
Now that readonly ref (in) is being added to the language, Dictionary.Contains, TryGetValue etc. can all use "in" parameters as they only read from the input. This would improve dictionary lookups of keys which value-tuples since they would be passed by ref and not by value.
Really this is relavent for any method that doesn't modify its parameters. This may be a clr/jit level optimization, since this can be identified by an analyser.
The text was updated successfully, but these errors were encountered: