Sunday, April 12, 2009

mutex micro benchmark

when working on mutex contention for ndbapi (mysql-cluster)
i decided to do some micro benchmarks.

The benchmark is threads that locks/unlocks an private mutex
and increment a counter.

The tests are:
  • mutex_aligned, pthread_mutex, lock/unlock, each mutex in separate cache-line
  • mutex_non_aligned, same as above but mutexes are packed together hence sharing cache-lines
  • spin_aligned, home-made spinlock (only x86), each spinlock in separate cache-line, the spinlock is an atomic operation for lock, and a full-barrier+assign for unlock
  • spin_non_aligned, same as above but spinlocks are packed together hence sharing cache-lines
  • lock_xadd, atomic-inc, (on sparc impl. using atomic.h, which uses cas i think)
  • xadd, (only x86), the non-smp (but irq) safe add variant for x86
  • gcc_sync_fetch_and_add, gcc intrinsic for atomic add
  • add_mb, "normal" add (on volatile variable) followed by a full-barrier
  • add, "normal" add (on volatile variable)
  • nop, a nop, just to see that thread start/stop does not affect test outcome noticable

The conclusions are:
  • atomic operations are very expensive
  • false sharing is a true disaster
  • it might be worth the effort to impl. both spinlocks and atomic-inc for sparc


Sorry for lousy html formatting :(
Intel(R) Core(TM)2 Quad CPU Q6600@2.40GHz (1-socket 4-cores)
mops vs threads
opns/op1234567
mutex_align4223446688787989
mutex_non_align42237108191822
spin_align1660121182234184196212
spin_non_align1660162432394057
lock_xadd8117235352470357352411
xadd23426841026136885510261196
gcc_sync_fetch_and_add8119239359479371359419
add_mb5171342513684455513598
add23987971195159499611961394
nop063571422870967287096721190471390625898989687258
2 x Intel(R) Xeon(R) CPU X5355 @2.66GHz (2-socket 4 cores each)
mops vs threads
opns/op1234567891011121314
mutex_align4322426384105126145162126134132141139155
mutex_non_align432210151818222927273336444957
spin_align1756112166210275292273260318270345312354346
spin_non_align17561736385149505572919312387120
lock_xadd1098195289377467513504504442420525512582605
xadd2380742106011891490161018291350168717601954171414252006
gcc_sync_fetch_and_add1098195287375466560488680523583556622587597
add_mb7126252369479587589770719598650639686649602
add244386197413931775180719041740198621391679155523072116
nop04114457328365323551721366000903439803529617540640712532761466530410950382418351699320356
SUNW,T5240, 2*(HT-64) 1415MHz SUNW,UltraSPARC-T2+ (2-socket 8-cores each, 8 threads/core)
mops vs threads
opns/op191725334149576573818997105113121
mutex_align299329557898115132141153161179181191200208209
mutex_non_align299371322293744515763687378838892
lock_xadd7014125232326408472506538536520512503499492487477
add_mb3428258469637759853909937947926915897881893892870
add137463710201257139814121356129512221247127312461265127212861287
nop018433146367248491752012893106769051761666976196549249604069373934863289

5 comments:

Ivan Novick said...

Why does it seem spin_lock starts fast but is getting a lot slower as you increase the threads whereas mutexes are not getting as slow as the thread count goes up?

Also, do you think you could share the code you used for these tests?

Regards,
Ivan Novick

Jonas Oreland said...

Hi,

1) I don't understand your comment about spin locks/mutexes.
Both spinlocks and mutexes run/"scales" well in the "aligned" case (i.e no false sharing) and runs/"scales" really bad when false-sharing occurs ("non_aligned")
Or?

2) sharing the code
sure, i don't know where to put it though...can you host it ?

/Jonas

Ivan Novick said...

I can put it on novickscode.com and attribute your name to it... also make sure to put your name and copyright in the code if you want me to do that.

I would really like to see the code, then I can see exactly what you are talking about. I did a similar test but not as thorough as yours and I really want to understand this issue fully.

My gmail id is novickivan if you want to correspond offline.

Regards,
Ivan Novick

Jonas Oreland said...

Created github repository:
http://github.com/jonasoreland/micro-benchmarks

Ivan Novick said...

thanks Jonas