Linuxのfutexが競合する場合、システムはスピンロックに多くの時間を費やすことがわかりました。これは、futexが直接使用されていない場合でも、malloc / free、rand、glib mutex呼び出し、およびfutexを呼び出すその他のシステム/ライブラリ呼び出しを呼び出す場合にも問題になることに気付きました。この動作を取り除く方法はありますか?
カーネル2.6.32-279.9.1.el6.x86_64でCentOS6.3を使用しています。また、kernel.orgから直接ダウンロードした最新の安定したカーネル3.6.6も試しました。
元々、この問題は16GBのRAMを搭載した24コアサーバーで発生していました。プロセスには700のスレッドがあります。「perfrecord」で収集されたデータは、スピンロックが__lll_lock_wait_privateおよび__lll_unlock_wake_privateから呼び出されたfutexから呼び出され、CPU時間の50%を消費していることを示しています。gdbを使用してプロセスを停止すると、バックトレースは、__lll_lock_wait_private__lll_unlock_wake_privateへの呼び出しがmallocから行われ無料であることを示していました。
私は問題を減らそうとしていたので、スピンロックの問題を引き起こしているのは実際にfutexであることを示す簡単なプログラムを作成しました。
8つのスレッドを開始し、各スレッドは次のことを行います。
//...
static GMutex *lMethodMutex = g_mutex_new ();
while (true)
{
static guint64 i = 0;
g_mutex_lock (lMethodMutex);
// Perform any operation in the user space that needs to be protected.
// The operation itself is not important. It's the taking and releasing
// of the mutex that matters.
++i;
g_mutex_unlock (lMethodMutex);
}
//...
私はこれを十分なRAMを備えた8コアマシンで実行しています。
「トップ」を使用して、マシンが10%アイドル、ユーザーモードで10%、システムモードで90%であることを確認しました。
「perftop」を使用して、私は次のことを観察しました。
50.73% [kernel] [k] _spin_lock
11.13% [kernel] [k] hpet_msi_next_event
2.98% libpthread-2.12.so [.] pthread_mutex_lock
2.90% libpthread-2.12.so [.] pthread_mutex_unlock
1.94% libpthread-2.12.so [.] __lll_lock_wait
1.59% [kernel] [k] futex_wake
1.43% [kernel] [k] __audit_syscall_exit
1.38% [kernel] [k] copy_user_generic_string
1.35% [kernel] [k] system_call
1.07% [kernel] [k] schedule
0.99% [kernel] [k] hash_futex
futexコードはfutex待機キューを取得する必要があるため、このコードはスピンロックでしばらく時間を費やすと思います。また、このコードスニペットでは、ユーザースペースで実行されているコードがほとんどないため、コードがシステム内である程度の時間を費やすことも予想されます。ただし、特にこのcpu時間が他の有用な作業を行うために必要な場合、スピンロックに費やされる時間の50%は過剰であるように思われます。