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

Hoist volatile variable's access outside the loop #34225

Merged
merged 2 commits into from
Mar 30, 2020

Conversation

kunalspathak
Copy link
Member

_tables is a volatile object and it has _countPerLock volatile field. On ARM64, JIT generates memory barrier instruction "dmb" for every volatile variable access which could be expensive. This PR caches the volatile variables outside the loop and use cached local variables instead. All the places where I have hoisted the variable access are guarded by AcquireAllLocks() method.

Fixes: #34198

`_tables` is a volatile object and it has `_countPerLock` volatile field.
On ARM64, JIT generates memory barrier instruction "dmb" for every volatile
variable access which could be expensive. This PR caches the volatile
variables outside the loop and use cached local variables instead.

Fixes: dotnet#34198
Copy link
Member

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

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

Thanks.

@kunalspathak
Copy link
Member Author

Test failures are related to #28553.

@maxim-kuvyrkov
Copy link

To satisfy my curiosity ... Do I understand correctly that semantics of "volatile" in C# does /not/ require compiler to preserve the number of reads and writes of volatile variables? (This is unlike C/C++ where language standard prevents a similar optimisation.)

@markusschaber
Copy link

@maxim-kuvyrkov I'm also a bit irritated - I also thought the whole point of volatile is to prevent the compiler from optimizing away actual accesses...

@stephentoub
Copy link
Member

Do I understand correctly that semantics of "volatile" in C# does /not/ require compiler to preserve the number of reads and writes of volatile variables?

Why do you think it doesn't?

@maxim-kuvyrkov
Copy link

maxim-kuvyrkov commented Sep 3, 2020

Do I understand correctly that semantics of "volatile" in C# does /not/ require compiler to preserve the number of reads and writes of volatile variables?

Why do you think it doesn't?

Because a statement hoisted from a loop will execute once, instead of the number of loop iterations.
Or are you asking about something else?

@stephentoub
Copy link
Member

stephentoub commented Sep 3, 2020

Because a statement hoisted from a loop will execute once, instead of the number of loop iterations.

Did you look at the change? It's not changing the compiler/JIT. it's manually moving a read out of a specific loop because it's not necessary to re-read this particular field on every iteration of this particular loop, but as a volatile it would be.

@maxim-kuvyrkov
Copy link

@stephentoub , thanks, this clears things up. No, I didn't read the code and from [1] I assumed that this change is for JIT. So C#'s "volatile" semantics mandates unchanged read/write count like C/C++?

[1] https://devblogs.microsoft.com/dotnet/arm64-performance-in-net-5/

@ghost ghost locked as resolved and limited conversation to collaborators Dec 10, 2020
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.

Hoist access to volatile variables out of loop in ConcurrentDictionary
6 participants