Linuxのフューテックスが競合すると、システムはスピンロックに多くの時間を費やすことがわかりました。フューテックスが直接使われていなくても、malloc/free、rand、glib mutex呼び出し、futexを呼び出すシステム/ライブラリ呼び出しを呼び出すときにも問題であることに気付きました。 ありますか?この動作を取り除く方法はですか?futexを競合するときのシステムCPU使用率が高い
カーネル2.6.32-279.9.1.el6.x86_64でCentOS 6.3を使用しています。私はkernel.orgから直接ダウンロードした最新の安定版カーネル3.6.6も試しました。
元はで、16GBのRAMを搭載した24コアサーバーで問題が発生しました。プロセスには700スレッドがあります。 "perf record"で収集されたデータは、スピンロックが__lll_lock_wait_privateと__lll_unlock_wake_privateから呼び出されたフューテックスから呼び出され、CPU時間の50%を奪っていることを示しています。 gdbでプロセスを停止したとき、backtracesはmallocとfreeから__lll_lock_wait_private __lll_unlock_wake_privateの呼び出しが行われたことを示しました。
私はこの問題を軽減しようとしていたので、スピンロック問題の原因となっているのは実際にはfutexesであることを示す簡単なプログラムを書きました。
スタート次の操作を行って、各スレッドと8つのスレッド、:私はRAMをたっぷり使って、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);
}
//...
。
"top"を使用して、マシンが10%アイドル状態、10%がユーザモード、90%がシステムモードであることがわかりました。私はのfutexコードはのfutex待ちキューを取得することがあるので、このコードは、スピンロックで一部の時間を費やすことを期待する
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
:
は「PERFトップ」を使用して、私は次のように観察しました。このコードのスニペットでは、ユーザー空間で実行されるコードはほとんどないため、コードをシステムに費やすことも期待しています。しかし、スピンロックで費やされる時間の50%は、特にこのCPU時間が他の有用な作業を行うために必要な場合には、過剰と思われます。
あなたは、どのような振る舞いが見たいか、いくつか言いたいことがあります。私はこれが完全にはっきりしていないと感じています。 – NPE
上記の例のようにmutexまたはfutexを使用して変数を同時にインクリメントすると、アトミックなインクリメント(50〜500倍効率的)で直接行うことができます。 「実際の」コード、すなわち実際に何かを行うコードでは、渋滞と時間がむしろ無視できるほどの詳細を浪費していることがわかります。実際のコードは、一度に6ダースのスレッドからのロックを競合しません。 – Damon
元々は、フューテックスがユーザコードから直接呼び出されない場合でも、これは問題であることに気付きました。これは、malloc/free、rand、glib mutex呼び出し、およびfutexを呼び出すシステム/ライブラリ呼び出しを呼び出すときに発生します。問題の説明に記載されているコードスニペットは、問題が発生したことを示すためのものであり、決して有用な作業ではありません。実際、mutexへの呼び出しの間のコードは、任意のユーザーコードにすることができます。 –