Ich habe einen Thread-Code, der PThreads unter Linux verwendet, der, wie ich vermute, unter übermäßigen Sperrkonflikten leidet. Welche Tools stehen mir zur Verfügung, um dies zu messen?
Solaris hat DTrace und plockstat. Gibt es etwas ähnliches unter Linux? (Ich weiß von einer kürzlich erschienenen DTrace-Portierung für Linux, aber sie scheint noch nicht bereit für die Hauptsendezeit zu sein.)
Nachdem ich mit SystemTap nicht viel Glück hatte, beschloss ich, trotz des Fehlens eines plockstat-Anbieters mit einigem Erfolg zu versuchen, die DTrace-Linux-Portierung zu verwenden. Das folgende DTrace-Skript ist nicht ganz a plockstat Ersatz, aber es gelang mir, mir einige der Informationen zu zeigen, nach denen ich gesucht hatte.
#!/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;
}
Hier ist ein Beispiel, das das obige DTrace-Skript verwendet, um die in FUTEX_WAIT verbrachte Zeit für ein einfaches Testprogramm daraus zu messen DTrace-Artikel.
$ ./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
Definitiv nicht großartig, aber zumindest ist es ein Ausgangspunkt.
Die neuesten Versionen von Valgrind verfügen über Sperrkonflikt- und Sperrvalidierungstools:
Was großartig ist, wenn Sie das Problem unter Valgrind erzeugen können (es wirkt sich auf die Laufzeitgeschwindigkeit des Codes aus) und über genügend Speicher verfügen, um Valgrind auszuführen.
Für andere Anwendungen wird das härtere Linux Trace Toolkit NG empfohlen:
Danke für deinen Vorschlag, aber Valgrind mag die Anwendung, die ich teste, wirklich nicht und kotzt sehr schnell.
– Luis Oliveira
9. August 2009 um 15:46 Uhr
Dieser Link ist tot. Ich finde lttng.org ist heutzutage der richtige Ort, um nachzusehen.
– Itkovian
22. Januar 2020 um 8:35 Uhr
Die neueste Version von systemtap enthält viele Beispielskripte. Eine davon scheint ein guter Ausgangspunkt zu sein, um Ihnen bei der Erfüllung Ihrer Aufgabe zu helfen:
#! /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
thread_blocktime
}
probe syscall.futex.return {
t = tid()
ts = thread_blocktime
if (ts) {
elapsed = gettimeofday_us() - ts
lock_waits[pid(), thread_thislock
delete thread_blocktime
delete thread_thislock
}
}
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]))
}
Ich habe zuvor versucht, etwas Ähnliches mit einem MySQL-Prozess zu diagnostizieren, und eine Ausgabe ähnlich der folgenden mit dem obigen Skript beobachtet:
mysqld[3991] lock 0x000000000a1589e0 contended 45 times, 3 avg us
mysqld[3991] lock 0x000000004ad289d0 contended 1 times, 3 avg us
Während das obige Skript Informationen zu allen Prozessen sammelt, die auf dem System ausgeführt werden, wäre es recht einfach, es so zu ändern, dass es nur mit einem bestimmten Prozess oder einer bestimmten ausführbaren Datei funktioniert. Beispielsweise könnten wir das Skript so ändern, dass es ein Prozess-ID-Argument verwendet, und die Sonde beim Eingeben des futex-Aufrufs so ändern, dass sie folgendermaßen aussieht:
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
thread_blocktime
}
}
Offensichtlich können Sie das Skript auf viele Arten ändern, um es an das anzupassen, was Sie tun möchten. Ich möchte Sie ermutigen, sich die verschiedenen Beispielskripte für SystemTap anzusehen. Sie sind wahrscheinlich der beste Ausgangspunkt.
In Ermangelung von DTrace ist Ihre beste Wahl wahrscheinlich SystemTap. Hier ist ein positives Schreiben.