none
AwareLock::Contention spin count RRS feed

  • General discussion

  • We're using Monitor.Enter to protect a shared data structure and we're seeing high CPU on a 24-core box. A profile shows that most threads are spinning waiting for a lock. No thread is doing extensive work while holding the lock and everyone eventually acquires the lock after the spin wait.

    Spinning is great, if done in moderation, but what we're seeing is that the spinning is dominating the CPU, preventing real work from getting done thus freeing the lock.

    Digging into the sscli20 code (yeah, ancient, but it's what we have) we found this comment in AwareLock::Contention (sscli20\clr\src\vm\syncblk.cpp):

                    // Delay by approximately 2*i clock cycles (Pentium III).
                    // This is brittle code - future processors may of course execute this
                    // faster or slower, and future code generators may eliminate the loop altogether.
                    // The precise value of the delay is not critical, however, and I can't think
                    // of a better way that isn't machine-dependent.  

    And the while condition that determines how long to spin is:

    while (i < 20000*g_SystemInfo.dwNumberOfProcessors);

    A couple questions:

    1) Is that algorithm still accurate or have modern high-core-count machines been factored in? My guess is that it's the same given our observations.

    2) Is there any way to control the spin count? I don't see anything in the sscli20 code, but maybe something was added later.

    Monday, February 24, 2014 4:00 PM

All replies

  • What version of .Net?
    Monday, February 24, 2014 8:39 PM
  • Oops, sorry... 4.5.1 on Windows Server 2012 R2 Standard.

        Image path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
        FileVersion:      4.0.30319.34011 built by: FX45W81RTMGDR

        Image path: C:\Windows\System32\mscoree.dll
        FileVersion:      6.3.9600.16384 (winblue_rtm.130821-1623)

        Image path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscoreei.dll
        FileVersion:      4.0.30319.33440 built by: FX45W81RTMREL

    Monday, February 24, 2014 9:49 PM
  • You can download the .Net source code from http://referencesource.microsoft.com/netframework.aspx to see what the current behavior is.

    I don't see a way to control the spinning.

    It's possible that swapping out to a ReaderWriterLockSlim class will help relieve the contention, or figure out some sort of batch update algorithm.

    Tuesday, February 25, 2014 2:07 AM
  • I have the reference source but that appears to be for the C# side of things only. I don't see any cpp files in the 4, 4.5, or 4.5Update1 downloads. Am I missing something?

    We've considered other mechanisms and have already started profiling other options. Rolling our own synchronization is a last resort, hence the (somewhat optimistic) question. They're not easy to get right and we prefer to stand on the shoulders of giants when possible. .Net -almost- has what's needed but we're tripped up in just the way that the author of the code predicted. :)


    Tuesday, February 25, 2014 6:08 AM
  • Hi Vobince,

    If you have questions about C++, please post thread on the following link for effective response. https://social.msdn.microsoft.com/Forums/vstudio/en-US/home?forum=vcgeneral.

    Thank you for understanding.

    Regards,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, February 28, 2014 6:17 AM
    Moderator
  • It's not a question about C++, but about the CLR implementation.

    Sounds like the answer is that the algorithm is still the same as the Pentium III-era code we see in SSCLI and there is no way to adjust the amount of spinning. That's really too bad and I hope that the team takes a look at this area in an upcoming release. It's only going to get worse with machines with more cores.

    We ended up writing our own lock.

    Friday, February 28, 2014 7:02 PM
  • I was looking at CoreCLR on GitHub and remembered this old thread. The AwareLock::Contention function is now defined here: https://github.com/dotnet/coreclr/blob/cbf46fb0b6a0b209ed1caf4a680910b383e68cba/src/vm/syncblk.cpp#L3290

    I don't see any "20000*g_SystemInfo.dwNumberOfProcessors" multiplication there, so I guess the code has been changed after sscli20.

    Some of the spinlock settings appear to be tunable with Registry values or environment variables: https://github.com/dotnet/coreclr/blob/25272dba24d166f8075c28cce08ac911941fcfc0/src/inc/clrconfigvalues.h#L651

    The comment at line 83 says that the EXTERNAL prefix in e.g. EXTERNAL_SpinLimitProcFactor means "this value is available for anyone to use and is publicly documented". I did not find any existing documentation for SpinLimitProcFactor but the recent pull request https://github.com/dotnet/coreclr/pull/844 would add some.

    Monday, May 4, 2015 7:32 PM
  • https://github.com/dotnet/coreclr/blob/master/Documentation/project-docs/clr-configuration-knobs.md

    Now has

    SpinRetryCount Hex value specifying the number of times the entire spin process is repeated (when applicable)

    Monday, February 27, 2017 6:10 PM
  • Hmm, but this is CoreCLR settings, how does it apply to .NET 4.5+?

    What about LOB code base that is as old as .NET 2.0, not everything is possible to switch...

    Is there a similar settings for .Net CLR? Thanks...

    /IP/


    • Edited by theipavlu Saturday, March 11, 2017 10:00 PM gramarlyonline inserted some xml stuff
    Saturday, March 11, 2017 9:58 PM