2009-08-08 13 views
22

Ho un codice threadato che utilizza PThreads su Linux che, sospetto, soffre di eccessiva contesa del blocco. Quali strumenti sono disponibili per me per misurare questo?Come misurare la contesa di mutex?

Solaris ha DTrace e plockstat. C'è qualcosa di simile su Linux? (Conosco una porta DTrace recente per Linux ma non sembra essere ancora pronta per la prima serata.)

risposta

1

In assenza di DTrace, la vostra migliore scommessa è probabilmente SystemTap. Ecco una recensione positiva.

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

+0

Ho paura che il post sul blog menzioni esplicitamente che non era molto utile per misurare la contesa del blocco. –

+2

Nei commenti dice che non ha provato a risolvere i simboli però. – Eugene

+0

Buon punto, ci proverò. –

4

Dopo non avere molta fortuna con SystemTap, ho deciso di provare e utilizzare il DTrace Linux port con un certo successo, nonostante la mancanza di un fornitore di plockstat. Il seguente script DTrace non è un bel sostituto plockstat ma è riuscito a mostrarmi alcune delle informazioni che cercavo.

#!/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; 
} 

Ecco un esempio utilizzando lo script DTrace sopra per misurare il tempo trascorso in FUTEX_WAIT per un semplice programma di test da questo DTrace article.

$ ./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   

Sicuramente non eccezionale, ma almeno è un punto di partenza.

4

ultime versioni valgrind ha un conflitto di blocchi e strumenti di convalida di blocco:

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

che è grande se si può produrre la questione sotto Valgrind (effettua il time code run) e hanno memoria sufficiente per eseguire Valgrind.

Per altri usi, il nucleo più duro Linux Trace Toolkit NG è raccomandato:

http://ltt.polymtl.ca/

Cheers, Gilad

+0

Grazie per il tuo suggerimento ma valgrind non mi piace davvero l'applicazione che sto testando e barfs molto velocemente. –

4

L'ultima versione di systemtap viene fornito con un sacco di example scripts. Uno in particolare sembra che sarebbe server come un buon punto di partenza per aiutare a realizzare il vostro compito:

#! /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])) 
} 

stavo cercando di individuare eventuali qualcosa di simile con un processo di MySQL in precedenza e l'output osservato simile al seguente utilizzando lo script di cui sopra :

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

mentre lo script sopra raccoglie le informazioni su tutti i processi in esecuzione sul sistema, sarebbe abbastanza facile da modificare per lavorare solo su un determinato processo o eseguibile. Ad esempio, potremmo modificare lo script di prendere un argomento ID di processo e modificare la sonda entrando la chiamata futex a guardare come:

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() 
    } 
} 

Ovviamente, è possibile modificare i lotti di script di modi per soddisfare ciò che si vuole fare. Ti inviterei a dare un'occhiata ai vari script di esempio per SystemTap. Probabilmente sono il miglior punto di partenza.

13

mutrace è lo strumento: http://0pointer.de/blog/projects/mutrace.html

La sua facile da costruire, installare e utilizzare.

+0

Il codice sorgente non sembra essere più disponibile qui, ma è qui: https://github.com/dbpercona/mutrace –

+0

Il codice di Lennart è disponibile all'indirizzo: http://git.0pointer.net/mutrace.git/ – stsquad

Problemi correlati