pthreads - Improve low level lock performance when heavily contested
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 24 Jun 2021 03:14:44 +0000 (20:14 -0700)
committerAaron LI <aly@aaronly.me>
Sat, 26 Jun 2021 08:31:49 +0000 (16:31 +0800)
commit8afbe037830085c12ef0de863a5ff3203107e971
tree5c9b99557fe2912d03cb21b6ba296a9e7b37cf03
parent2ad04be3ef89f3567fb7a3623eb88c9ddec1e6c8
pthreads - Improve low level lock performance when heavily contested

* The low-level __thr_umtx_lock()/unlock and related primitives are
  used by pthreads, but have very poor performance when heavily contested:

  * Calling sched_yield() just doesn't work well.

  * Attempts to sleep too quickly, which costs a great deal of
    system overhead.

  * And issues broadcast wakeups for waiters, causing excessive IPIs.

* Stop calling sched_yield() in the loop.  Let the userland scheduler's
  dynamic priority deal with it.

* Scale the spin count up significantly, and then further based on
  the number of pthreads in the application.  If the program is stupid
  enough to cause excessive contention, then the penalty for making that
  perform well is going to be more cpu time.

* Issue a wakeup1() equivalent on unlock if there are any waiters,
  significantly reducing system IPIs.

  To make this work reliably, the primary lock loop, when it sleeps,
  will now always do so with a 1mS timeout, then loop/recheck.  If
  an API timeout is specified in excess of 1mS, the timo variable
  is reduced on each loop and proper timeout handling occurs on
  the last call.

* Running qemu w/ 32-cores specified (on a 64/128 threadripper host),
  with nvmm, reduces build-all time from 9:10 to 8:20, relative to
  a native host build time (usched restricted to 32 cores) of 6:11.
  So this is a significant improvement.

  (currently qemi-6.0.0 w/nvmm has some significant contention when a
   high cpu count is configured, due to the implementation).
lib/libthread_xu/thread/thr_umtx.c