2009-08-08 56 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