• Dmitry Vyukov's avatar
    sync: add active spinning to Mutex · edcad863
    Dmitry Vyukov authored
    Currently sync.Mutex is fully cooperative. That is, once contention is discovered,
    the goroutine calls into scheduler. This is suboptimal as the resource can become
    free soon after (especially if critical sections are short). Server software
    usually runs at ~~50% CPU utilization, that is, switching to other goroutines
    is not necessary profitable.
    
    This change adds limited active spinning to sync.Mutex if:
    1. running on a multicore machine and
    2. GOMAXPROCS>1 and
    3. there is at least one other running P and
    4. local runq is empty.
    As opposed to runtime mutex we don't do passive spinning,
    because there can be work on global runq on on other Ps.
    
    benchmark                   old ns/op     new ns/op     delta
    BenchmarkMutexNoSpin        1271          1272          +0.08%
    BenchmarkMutexNoSpin-2      702           683           -2.71%
    BenchmarkMutexNoSpin-4      377           372           -1.33%
    BenchmarkMutexNoSpin-8      197           190           -3.55%
    BenchmarkMutexNoSpin-16     131           122           -6.87%
    BenchmarkMutexNoSpin-32     170           164           -3.53%
    BenchmarkMutexSpin          4724          4728          +0.08%
    BenchmarkMutexSpin-2        2501          2491          -0.40%
    BenchmarkMutexSpin-4        1330          1325          -0.38%
    BenchmarkMutexSpin-8        684           684           +0.00%
    BenchmarkMutexSpin-16       414           372           -10.14%
    BenchmarkMutexSpin-32       559           469           -16.10%
    
    BenchmarkMutex                 19.1          19.1          +0.00%
    BenchmarkMutex-2               81.6          54.3          -33.46%
    BenchmarkMutex-4               143           100           -30.07%
    BenchmarkMutex-8               154           156           +1.30%
    BenchmarkMutex-16              140           159           +13.57%
    BenchmarkMutex-32              141           163           +15.60%
    BenchmarkMutexSlack            33.3          31.2          -6.31%
    BenchmarkMutexSlack-2          122           97.7          -19.92%
    BenchmarkMutexSlack-4          168           158           -5.95%
    BenchmarkMutexSlack-8          152           158           +3.95%
    BenchmarkMutexSlack-16         140           159           +13.57%
    BenchmarkMutexSlack-32         146           162           +10.96%
    BenchmarkMutexWork             154           154           +0.00%
    BenchmarkMutexWork-2           89.2          89.9          +0.78%
    BenchmarkMutexWork-4           139           86.1          -38.06%
    BenchmarkMutexWork-8           177           162           -8.47%
    BenchmarkMutexWork-16          170           173           +1.76%
    BenchmarkMutexWork-32          176           176           +0.00%
    BenchmarkMutexWorkSlack        160           160           +0.00%
    BenchmarkMutexWorkSlack-2      103           99.1          -3.79%
    BenchmarkMutexWorkSlack-4      155           148           -4.52%
    BenchmarkMutexWorkSlack-8      176           170           -3.41%
    BenchmarkMutexWorkSlack-16     170           173           +1.76%
    BenchmarkMutexWorkSlack-32     175           176           +0.57%
    
    "No work" benchmarks are not very interesting (BenchmarkMutex and
    BenchmarkMutexSlack), as they are absolutely not realistic.
    
    Fixes #8889
    
    Change-Id: I6f14f42af1fa48f73a776fdd11f0af6dd2bb428b
    Reviewed-on: https://go-review.googlesource.com/5430Reviewed-by: 's avatarRick Hudson <rlh@golang.org>
    Run-TryBot: Dmitry Vyukov <dvyukov@google.com>
    edcad863
proc1.go 87.1 KB