24

Linux で PThreads を使用するスレッド化されたコードがいくつかありますが、これは過度のロック競合に苦しんでいると思われます。これを測定するために利用できるツールは何ですか?

Solaris には DTrace と plockstat があります。Linuxに似たようなものはありますか?(Linux 用の最近の DTrace 移植については知っていますが、まだ準備が整っていないようです。)

4

5 に答える 5

15

mutrace はツールです: http://0pointer.de/blog/projects/mutrace.html

構築、インストール、使用が簡単です。

于 2010-07-14T12:00:43.160 に答える
5

SystemTap でうまくいかなかったので、plockstat プロバイダーがないにもかかわらず、DTrace Linux ポートを試してみることにしました。次の 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 記事の単純なテスト プログラムの 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        

確かに素晴らしいことではありませんが、少なくとも出発点です。

于 2009-08-09T01:12:22.630 に答える
4

valgrind の最新バージョンには、ロック競合とロック検証ツールがあります。

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

Valgrind で問題を生成でき (コードの実行速度に影響します)、Valgrind を実行するのに十分なメモリがあれば、これは素晴らしいことです。

その他の用途には、よりハードコアな Linux Trace Toolkit NG が推奨されます。

http://ltt.polymtl.ca/

乾杯、ギラッド

于 2009-08-09T12:01:23.503 に答える
4

systemtap の最新バージョンには、多数のサンプル スクリプトが付属しています。特に、タスクの達成を支援するための良い出発点として役立つように思われるものがあります。

#! /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 のさまざまなサンプル スクリプトをご覧になることをお勧めします。それらはおそらく最良の出発点です。

于 2010-07-14T03:44:17.670 に答える
1

DTrace がない場合、最善の策はおそらくSystemTapです。ここにポジティブな書き込みがあります。

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

于 2009-08-08T19:42:44.263 に答える