2009-08-08 57 views
22

我有一些使用Linux上的PThreads的線程代碼,我懷疑是遭受了過度的鎖爭用。我有什麼工具可以衡量這一點?如何衡量互斥量爭用?

Solaris有DTrace和plockstat。 Linux上有類似的東西嗎? (我知道最近用於Linux的DTrace端口,但它似乎還沒有準備好黃金時間。)

回答

1

在沒有DTrace的情況下,您最好的選擇可能是SystemTap。這是一個積極的寫作。

http://davidcarterca.wordpress.com/2009/05/27/systemtap/

+0

恐怕博客文章明確提到它對衡量鎖爭用並不是很有用。 – 2009-08-08 20:02:29

+2

在評論中他說他沒有嘗試解析符號。 – Eugene 2009-08-08 20:27:19

+0

好點,我會試試看。 – 2009-08-08 20:39:53

4

不具有的SystemTap多少運氣之後,我決定嘗試,使用DTrace Linux port取得了一些成功,儘管缺少plockstat提供的。以下DTrace腳本並不完全代替plockstat,但它能夠向我展示一些我之後的信息。

#!/usr/sbin/dtrace -s 

/* Usage: ./futex.d '"execname"' */ 

long total; 

END 
{ 
    printf("total time spent on futex(): %ldms\n", total); 
} 

/* arg1 == 0 means FUTEX_WAIT */ 
syscall::futex:entry 
/execname == $1 && arg1 == 0/ 
{ 
    self->start = timestamp; 
} 

syscall::futex:return 
/self->start/ 
{ 
    this->elapsed = (timestamp - self->start)/1000000; 
    @[execname] = quantize(this->elapsed); 
    total += this->elapsed; 
    self->start = 0; 
} 

下面是使用上述DTrace腳本以測量從該DTrace article在FUTEX_WAIT花費一個簡單的測試程序的時間的例子。

$ ./futex.d '"mutex-test"' 
dtrace: script './futex.d' matched 3 probes 
^C 
CPU  ID     FUNCTION:NAME 
    1  2        :END total time spent on futex(): 11200ms 


    mutex-test           
      value ------------- Distribution ------------- count  
      128 |           0   
      256 |@@@@@@@@@@@@@@@@@@@@      1   
      512 |           0   
      1024 |           0   
      2048 |           0   
      4096 |           0   
      8192 |@@@@@@@@@@@@@@@@@@@@      1   
      16384 |           0   

絕對不是很好,但至少它是一個起點。

4

Valgrind的最新版本,有鎖爭用,鎖驗證工具:

http://valgrind.org/docs/manual/drd-manual.html

這是偉大的,如果你能生產Valgrind的下問題(它影響的代碼運行時的速度),並有足夠的內存運行Valgrind的。

作其他用途,更硬Linux核心跟蹤工具包NG建議:

http://ltt.polymtl.ca/

乾杯, 吉拉德

+0

感謝您的建議,但valgrind真的不喜歡我測試的應用程序和真正快速的barf。 – 2009-08-09 15:46:08

4

SystemTap的最新版本帶有很多example scripts。其中特別是似乎將服務器作爲一個很好的起點,幫助你完成你的任務:

#! /usr/bin/env stap 

global thread_thislock 
global thread_blocktime 
global FUTEX_WAIT = 0 

global lock_waits 
global process_names 

probe syscall.futex { 
    if (op != FUTEX_WAIT) next 
    t = tid() 
    process_names[pid()] = execname() 
    thread_thislock[t] = $uaddr 
    thread_blocktime[t] = gettimeofday_us() 
} 

probe syscall.futex.return { 
    t = tid() 
    ts = thread_blocktime[t] 
    if (ts) { 
    elapsed = gettimeofday_us() - ts 
    lock_waits[pid(), thread_thislock[t]] <<< elapsed 
    delete thread_blocktime[t] 
    delete thread_thislock[t] 
    } 
} 

probe end { 
    foreach ([pid+, lock] in lock_waits) 
    printf ("%s[%d] lock %p contended %d times, %d avg us\n", 
      process_names[pid], pid, lock, @count(lock_waits[pid,lock]), 
      @avg(lock_waits[pid,lock])) 
} 

我試圖診斷與MySQL進程先前類似類似於使用上面的腳本下面的內容並觀察輸出:

mysqld[3991] lock 0x000000000a1589e0 contended 45 times, 3 avg us 
mysqld[3991] lock 0x000000004ad289d0 contended 1 times, 3 avg us 

雖然上面的腳本收集的系統上運行的所有進程的信息,這將是很容易將它修改爲只工作在某個進程或可執行文件。例如,我們可以修改腳本以一個進程ID參數,並修改進入futex的電話看起來像探頭:

probe begin { 
    process_id = strtol(@1, 10) 
} 

probe syscall.futex { 
    if (pid() == process_id && op == FUTEX_WAIT) { 
    t = tid() 
    process_names[process_id] = execname() 
    thread_thislock[t] = $uaddr 
    thread_blocktime[t] = gettimeofday_us() 
    } 
} 

很明顯,你可以修改腳本很多方法來適應你想要什麼做。我鼓勵你看看SystemTap的各種示例腳本。他們可能是最好的起點。

13

mutrace是工具: http://0pointer.de/blog/projects/mutrace.html

它易於構建,安裝和使用。

+0

源代碼似乎不再可用,但它在這裏:https://github.com/dbpercona/mutrace – 2016-03-18 00:59:04

+0

Lennart的代碼可以在http://git.0pointer.net/mutrace.git/找到。 – stsquad 2016-11-03 16:25:46