我觀察到,當linux futexes競爭時,系統花費了很多時間在自旋鎖中。我注意到即使不直接使用futexes也是一個問題,而且在調用malloc/free,rand,glib mutex調用以及調用futex的其他系統/庫調用時也會出現問題。有沒有ANY擺脫這種行爲的方法?競爭futex時高系統CPU使用率
我正在使用內核2.6.32-279.9.1.el6.x86_64的CentOS 6.3。我也嘗試了從kernel.org直接下載的最新的穩定內核3.6.6。
本來,問題發生在一臺配備16GB RAM的24核心服務器上。該進程有700個線程。使用「perf記錄」收集的數據顯示自旋鎖是從__lll_lock_wait_private和__lll_unlock_wake_private調用的futex中調用的,正在佔用50%的CPU時間。當我用gdb停止進程時,回溯顯示調用__lll_lock_wait_private __lll_unlock_wake_private是由malloc和free創建的。
我試圖減少這個問題,所以我寫了一個簡單的程序,顯示它確實是導致螺旋鎖問題的futexes。
啓動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);
}
//...
我是一個8核的機器上運行這個,用大量的RAM。
使用「頂部」,我發現機器空閒10%,用戶模式下10%,系統模式下90%。
使用「PERF頂部」,我觀察到以下:
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的等待隊列。我也希望代碼在系統中花費一些時間,因爲在這段代碼中,用戶空間中運行的代碼非常少。然而,花費在自旋鎖上的時間有50%似乎過多,特別是當這個CPU時間需要做其他有用的工作時。
您可能想談談您希望看到的行爲。我覺得這並不完全清楚。 – NPE
使用互斥鎖或futex來同時增加變量(如上例所示)有點愚蠢,因爲這可以直接使用原子增量(效率高出50至500倍)完成。在「真實」代碼中,即實際上做了某些事情的代碼,我發現擁擠和浪費的時間浪費在旋轉而非可忽略的細節上。實時代碼不會同時爭奪六個線程的鎖定。 – Damon
最初,我注意到這是一個問題,即使futexes不是直接從用戶代碼調用;調用malloc/free,rand,glib mutex調用以及調用futex的其他系統/庫調用時會發生這種情況。問題描述中給出的代碼片段僅僅是爲了展示問題的發生,而絕不代表任何有用的工作。實際上,互斥調用之間的代碼可以是任何用戶代碼。 –