Live data from Hacker News

Spinning around: Please don’t – Common problems with spin locks

siliceum.com

31–40 of 66 posts

Re: Spinning around: Please don’t – Common problems with spin locks

#31
My concurrency knowledge is a bit rusty but aren't spinlocks only supposed to be used for very brief waits like in the hundreds of cycles (or situations where you can't block... like internal o/s scheduling structures in SMP setups)? If so how much does all this back off and starvation of higher priority threads even matter? If it is longer then you should use a locking primitive (except for in those low level os structures!) where most of the things discussed are not an issue. Would love to hear the use cases where spin locks are needed in eg user space, I dont doubt they occur.

Re: Spinning around: Please don’t – Common problems with spin locks

#32
what is/are the thread synchronization protocol called which is the equivalent to ethernet's CSMA? there's no "carrier sensing", but instead "who won or mistakes were made" sensing. or is that just considered a form of spinlock? (you're not waiting for a lock, you perform your operation then see if it worked; though you could make the operation be "acquire lock" in which case it's a spinlock)

Re: Spinning around: Please don’t – Common problems with spin locks

#33
I struggled with this in Wine. "malloc" type memory allocation involves at least two levels of spinlocks. When you do a "realloc", the spinlocks are held during the copying operation. If you use Vec .push in Rust, you do a lot of reallocs. In a heavily multithreaded program, this can knock performance down by more than two orders of magnitude. It's hard to reproduce this with a simple program; it takes a lot of concurrency to hit futex congesion.

Real Windows, and Linux, don't have this problem. Only Wine's "malloc" in a DLL, which does.

Bug reports resulted in finger-pointing and denial.[1] "Unconfirmed", despite showing debugger output.

[1] https://bugs.winehq.org/show_bug.cgi?id=54979

Re: Spinning around: Please don’t – Common problems with spin locks

#35
post #33

I struggled with this in Wine. "malloc" type memory allocation involves at least two levels of spinlocks. When you do a "realloc", the spinlocks are held during the copying operation. If you use Vec .push in Rust, you do a lot of reallocs. In a heavily multithreaded program, this can knock performance down by more than two orders of magnitude. It's hard to reproduce this with a simple program; it takes a lot of concu…

Reading the bug report, I don't see any denial. The maintainers are pretty clear that they acknowledge the issue, but don't know how to fix it.

Re: Spinning around: Please don’t – Common problems with spin locks

#36

TFA lists WebKit as a project that "does it wrong". The author should read https://webkit.org/blog/6161/locking-in-webkit/ so that they understand what they are talking about. WebKit does it right in the sense that: - It as an optimal amount of spinning - Threads wait (instead of spinning) if the lock is not available immediately-ish And we know that the algorithms are optimal based on rigorous experiments.

This is an incredible blog post. Super educational, and I think directly applicable to my work. Thanks for sharing!

Re: Spinning around: Please don’t – Common problems with spin locks

#37

TFA lists WebKit as a project that "does it wrong". The author should read https://webkit.org/blog/6161/locking-in-webkit/ so that they understand what they are talking about. WebKit does it right in the sense that: - It as an optimal amount of spinning - Threads wait (instead of spinning) if the lock is not available immediately-ish And we know that the algorithms are optimal based on rigorous experiments.

The author (me) actually read this long ago

> - It as an optimal amount of spinning

No it isn't, it has a fixed number of yields, which has a very different duration on various CPUs

> Threads wait (instead of spinning) if the lock is not available immediately-ish

They use parking lots, which is one way to do futew (in fact, WaitOnAddress is implemented similarly). And no if you read the code, they do spin. Worse, they actually yield the thread before properly parking.

Re: Spinning around: Please don’t – Common problems with spin locks

#38
post #5

The basic rule of writing your own cross-thread datastructures like mutexes or condition variables is... don't, unless you have very good reason not to. If you're in that rare circumstance where you know the library you're using isn't viable for some reason, then the next best rule is to use your OS's version of a futex as the atomic primitive, since it's going to solve most of the pitfalls for you automatically. The…

As always: use standard libraries first, profile, then write your own if the data indicate that it's necessary. To your point, the standard library probably already uses the OS primitives under the hood, which themselves do a short userspace spin-wait and then fall back to a kernel wait queue on contention. If low latency is a priority, the latter might be unacceptable. The following is an interesting talk where the…

> which themselves do a short userspace spin-wait and then fall back to a kernel wait queue on contention.

Yes, but sadly not all implementations... The point remains that you should prefer OS primitives when you can, profile first, reduce contention, and then only, maybe, if you reeeally know what you're doing, on a system you mostly know and control, then perhaps you may start doing it yourself. And if you do, the fallback under contention must be the OS primitive

Re: Spinning around: Please don’t – Common problems with spin locks

#39

Nice article! Yes, using spinlocks in normal userspace applications is not recommended. One area where I found spinlocks to be useful is in multithreaded audio applications. Audio threads are not supposed to be preempted by other user space threads because otherwise they may not complete in time, leading to audio glitches. The threads have a very high priority (or have a special scheduling policy) and may be pinned t…

I've heard of issues on Arm devices with properly isolated cores (only one thread allowed, interrupts disabled) because the would interact with other threads using such a spinlock, threads which were not themselves isolated. The team replaced it all with a futex and it ended up working better in the end. Sadly this happened while I was under another project so I don't have the details, but this can be problematic in audio too. To avoid the delay of waking up thread you can actually wake them a tiny bit early and then spin (not on a lock), since you know work is incoming.

Re: Spinning around: Please don’t – Common problems with spin locks

#40
post #35
post #33

I struggled with this in Wine. "malloc" type memory allocation involves at least two levels of spinlocks. When you do a "realloc", the spinlocks are held during the copying operation. If you use Vec .push in Rust, you do a lot of reallocs. In a heavily multithreaded program, this can knock performance down by more than two orders of magnitude. It's hard to reproduce this with a simple program; it takes a lot of concu…

Reading the bug report, I don't see any denial. The maintainers are pretty clear that they acknowledge the issue, but don't know how to fix it.

Yes, although it took a while to get there. This confirms the OP's line "Spinning around: Please don't". You can get huge performance hits that are hard to fix. Huge.
Post reply on HN