17

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%は過剰であるように思われます。

4

1 に答える 1

3

私も同様の問題に遭遇しました。私の経験では、libc のバージョンや他の多くのあいまいなもの (たとえば、ここのような fork() の呼び出し) によっては、多くのロックとロック解除を行うと、パフォーマンスが低下したり、デッドロックが発生したりすることがあります。

この男はtcmallocに切り替えることでパフォーマンスの問題を解決しましたが、ユースケースによっては良い考えかもしれません。あなたにとっても試してみる価値があるかもしれません。

私にとっては、複数のスレッドで多くのロックとロック解除を行っているときに、再現可能なデッドロックが発生しました。2010 年から libc で Debian 5.0 rootfs (組み込みシステム) を使用していましたが、Debian 6.0 にアップグレードすることで問題が修正されました。

于 2012-11-08T21:23:18.597 に答える