thread pthread_create pthread create c linux pthreads dtrace

pthread_create - ¿Cómo medir la contención mutex?



pthread_create>() (5)

Tengo un código de subprocesos que usa PThreads en Linux que, sospecho, está sufriendo de una contención de bloqueo excesiva ¿Qué herramientas están disponibles para que mida esto?

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


Después de no tener mucha suerte con SystemTap, decidí probar y usar el puerto DTrace Linux con cierto éxito, a pesar de la falta de un proveedor de plockstat. El siguiente script de DTrace no es un reemplazo bastante plockstat pero logró mostrarme algo de la información que estaba 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; }

Este es un ejemplo que usa el script DTrace anterior para medir el tiempo empleado en FUTEX_WAIT para un programa de prueba simple de este artículo de DTrace .

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



La última versión de systemtap viene con muchos scripts de ejemplo . Uno en particular parece que sería un buen punto de partida para ayudarlo a cumplir 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])) }

Estaba intentando diagnosticar algo similar con un proceso MySQL anteriormente y observé una salida similar a la siguiente utilizando el script anterior:

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

Si bien la secuencia de comandos anterior recopila información sobre todos los procesos que se ejecutan en el sistema, sería bastante fácil modificarla para que solo funcione en un determinado proceso o ejecutable. Por ejemplo, podríamos cambiar la secuencia de comandos para tomar un argumento de ID de proceso y modificar la sonda al ingresar la llamada futex para que se vea como:

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 el script de muchas maneras para adaptarlo a lo que quiere hacer. Le animo a que eche un vistazo a los distintos scripts de ejemplo para SystemTap. Son probablemente el mejor punto de partida.


Las últimas versiones de valgrind tienen una contención de bloqueo y herramientas de validación de bloqueo

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

Lo que es genial si puede producir el problema bajo Valgrind (afecta la velocidad de ejecución del código) y tiene suficiente memoria para ejecutar Valgrind.

Para otros usos, se recomienda el Linux Trace Toolkit NG más duro:

http://ltt.polymtl.ca/

Saludos, Gilad