<div dir="ltr">Since this question has popped up, I looked at how the ethread part of locking is written for Windows (as opposed to Linux). The waits here also seem to spin potentially (on both Windows and POSIX implementation)<div>Linux implementation is using futexes while standard Windows events are used on Windows.</div><div><br></div><div>The question is what is the earliest version of Windows that should be officially supported since starting with Windows 8, there is a mechanism similar to futexes available (and everything which does not have this feature is pretty much EOL'ed from MS now)</div><div><a href="https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress">https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress</a> </div><div><a href="https://devblogs.microsoft.com/oldnewthing/20170601-00/?p=96265">https://devblogs.microsoft.com/oldnewthing/20170601-00/?p=96265</a> </div><div><br></div><div>I know that Windows port of Erlang is not a priority, but would it make sense to update the thread events to use WaitOnAddress/WakeByAddressXXX?<br></div><div>Before I do any experiments by myself I would like to know if the Erlang/OTP gurus see a potential gain here.</div><div><br></div><div>Thanks,</div><div>Jaka</div><div> <br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 15 Jan 2020 at 23:03, Rickard Green <<a href="mailto:rickard@erlang.org">rickard@erlang.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">On Wed, Jan 15, 2020 at 5:54 PM Andreas Schultz <<a href="mailto:andreas.schultz@travelping.com" target="_blank">andreas.schultz@travelping.com</a>> wrote:<br>><br>><br>><br>> Am Mi., 15. Jan. 2020 um 17:41 Uhr schrieb Jesper Louis Andersen <<a href="mailto:jesper.louis.andersen@gmail.com" target="_blank">jesper.louis.andersen@gmail.com</a>>:<br>>><br>>> On Tue, Jan 7, 2020 at 10:01 AM Andreas Schultz <<a href="mailto:andreas.schultz@travelping.com" target="_blank">andreas.schultz@travelping.com</a>> wrote:<br>>>><br>>>><br>>>> Could any of the Erlang gurus or ERTS developers comment on the use of home grown mutexes and spinlocks in Erlang in light of that discussion?<br>>>><br>>><br>>> Not a locking expert in the ERTS, but:<br>>><br>>> The locking API is there to provide a factoring point for the BEAM. The idea is that we have a locking API to use in ERTS which then maps to different implementations as we see fit. This allows us to target both UNIX, Windows, and embedded OS'es at the same time, with a consistent API. But it gets better than that!<br>>><br>>> We can use the factoring point to "plug in" different locking models and try them out. This allows us to choose a locking model which works well. It also allows us to plug in various debugging/correctness checks at compile time. For instance that lock ordering is preserved, if locks are contended on, or if a deadlock happened.<br>>><br>>> That is, the current locking model is sort-of chosen at compile time, based on the capabilities of the underlying system. <br>>><br>>> All in all, I'm going to claim that the system is not so much "home grown" as it is a sensible wrapper around an underlying system.<br>><br>><br>> I have seen the different underlying implementations for the locking primitives. There are wrappers for Windows and POSIX threads (pthread). But there also seems to be a completely independent implementation of mutexes and spinlocks that does not use the OS or libc provided primitives.<br>> On Linux that Erlang specific implementation appears to be used by default (that is what I called "home grown"). The pthread version is only used when Erlang is build with valgrind support (or so it seems).<br>><br>> I was thinking about hacking a build to use only the pthread locking primitives (without the other valdrind overhead) and run some benchmarks.<br>> However, my hope was that some Erlang expert could shed some light in the locking before I spent the time to do that.<br>><br>> Anyhow, does anybody have a suggestion for an existing benchmark that could demonstrate differences between locking primitives?<br>><br>> Andreas<br>><br>>><br>>><br>>> --<br>>> J.<br>><br>><br>><br>> --<br>><br>> Andreas Schultz<br><br><br>There are more or less no pure spinlocks left in the VM (there might be in some test-code and/or at some initialization phase). The last one at a potentially heavily contended place was removed not long ago though <<a href="http://erlang.org/download/OTP-22.1.8.README" target="_blank">http://erlang.org/download/OTP-22.1.8.README</a>>.<br><br>We have "homegrown" lock implementations that spin a while trying to acquire a lock that is locked. The spinning since it significantly improve performance. The spinning is bounded though and a thread not successfully acquiring a lock will eventually go to sleep.<br><br>The two major "homegrown" lock implementations:<br><br>-- Process locks --<br><br>Our process lock implementation is mainly a memory optimization. Each process (currently) have 5 different locks.The 5 locks of a process consumes 6 words in total. When using pthread mutexes 25 words are used (on my linux machine). Our process lock implementation also makes it cheaper to lock/unlock multiple locks of one processes in one operation. The cost of locking all 5 in one operation is the same as locking one of them.<br><br>-- Rwlocks --<br><br>This implementation came about since the NPTL *) rwlocks was not fair. By default a reader preferred approach was used by NPTL rwlocks which easily could (and did) starve writers. You could configure them as writer preferred which was a bit better, but the main problem with starvation still remained (in this case of readers). The performance of the NPTL rwlocks was also quite bad in most scenarios. I write "was" since I don't know if changes has been made since the last time I looked at this.<br><br>Besides being fair our rwlock implementation also have a reader optimized mode which improve performance in scenarios where you mostly only read-lock the rwlock. This by keeping track of readers in separate cachelines and by this avoiding cacheline ping-ponging. On a big smp machine this improvement can be huge. Such rwlocks are e.g. used when you pass the read_concurrency option to ets tables.<br><br>*) Native POSIX Thread Library (used on Linux)<br><br><br>The NPTL rwlocks was quite a disappointment, but NPTL mutexes was the opposite. The performance was really good. Especially in heavily contended cases. On Linux they are used for all "mutex-cases" except for process locks.<br><br>Regards,<br>Rickard<br>--<br>Rickard Green, Erlang/OTP, Ericsson AB</div>
</blockquote></div>