2009-08-08 12 views
22

Tengo un código enhebrado usando PThreads en Linux que, sospecho, está sufriendo una contención de bloqueo excesiva. ¿Qué herramientas hay disponibles para medir esto?¿Cómo medir la contención mutex?

Solaris tiene DTrace y plockstat. ¿Hay algo similar en Linux? (Sé sobre un puerto reciente de DTrace para Linux, pero parece que todavía no está listo para el horario de máxima audiencia)

Respuesta

1

En ausencia de DTrace, la mejor opción es probablemente SystemTap. Aquí hay un escrito positivo.

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

+0

Me temo que la publicación de blog menciona explícitamente que no fue muy útil para medir la contención de bloqueo. –

+2

En los comentarios, dice que no intentó resolver los símbolos sin embargo. – Eugene

+0

Buen punto, lo intentaré. –

4

Después de no tener mucha suerte con SystemTap, yo decidimos probar y usar el DTrace Linux port con cierto éxito, a pesar de la falta de un proveedor plockstat. El siguiente script de DTrace no es exactamente un reemplazo de plockstat, pero logró mostrarme parte de la información que estaba buscando.

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

Aquí hay un ejemplo usando la secuencia de comandos de DTrace anterior para medir el tiempo de permanencia en FUTEX_WAIT para un programa simple prueba de esta 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   

Definitivamente no es genial, pero al menos es un punto de partida.

4

últimas versiones valgrind tiene una contención de bloqueo y herramientas de validación de bloqueo:

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

que es grande si usted puede producir la cuestión que se Valgrind (que afecta a ejecutar código de velocidad tiempo) y tiene suficiente memoria para ejecutar Valgrind.

Para otras aplicaciones, el núcleo más duro de Linux Trace Toolkit GN se recomienda:

http://ltt.polymtl.ca/

Saludos, Gilad

+0

Gracias por su sugerencia pero valgrind realmente no le gusta la aplicación que estoy probando y barfs realmente rápido. –

4

la última versión del systemtap viene con un montón de example scripts. Uno en particular, parece que sería servidor como un buen punto de partida para ayudar a lograr su tarea:

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

yo estaba tratando de diagnosticar algo similar con un proceso de MySQL con anterioridad y la salida observada similar al siguiente usando la secuencia de comandos :

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

Mientras que el script anterior recoge información sobre todos los procesos que se ejecutan en el sistema, sería muy fácil para modificarlo para trabajar solamente en un determinado proceso o un ejecutable. Por ejemplo, podríamos cambiar el guión para tomar un argumento de ID de proceso y modificar la sonda al entrar en la llamada futex para parecerse a:

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

Obviamente, podría modificar los lotes de guiones de formas para adaptarse a lo que quiere hacer. Te animo a echar un vistazo a los diversos scripts de ejemplo para SystemTap. Ellos son probablemente el mejor punto de partida.

13

mutrace es la herramienta: http://0pointer.de/blog/projects/mutrace.html

Su fácil de construir, instalar y utilizar.

+0

El código fuente ya no parece estar disponible, pero está aquí: https://github.com/dbpercona/mutrace –

+0

El código de Lennart se puede encontrar en: http://git.0pointer.net/mutrace.git/ – stsquad