Das Profilerstellungsprogramm perf das mit dem Linux-Kernel ausgeliefert wird, ist äußerst nützlich, um das systemweite und Multi-Prozess-Verhalten zu untersuchen – aber es leistet viel mehr als die CPU-Profilierung, für die es oft verwendet wird. Sie haben sich wahrscheinlich perf top -az angesehen oder perf top -u postgres Ausgabe, aber das ist nur das kleinste bisschen von dem, was es tun kann. (Wenn Sie die TL/DR-Version wollen, springen Sie runter zu „User Space Dynamic Probes“).
Einer der großen Vorteile von perf ist, dass es nicht aufdringlich ist. Sie müssen keinen Debugger anhängen und die Ausführung unterbrechen. Sie müssen Befehle nicht direkt unter einem Profiler in einer speziellen Umgebung ausführen. Es ist nicht erforderlich, den Server neu zu starten, um eine problematische Workload zu debuggen, und oft ist es nicht erforderlich, mit Debug-Optionen neu zu kompilieren. Dies ist äußerst nützlich, wenn Sie versuchen, Leistungsprobleme in einem Live-System aufzuspüren, da Sie damit schnell und mit minimalen Auswirkungen Theorien darüber testen können, was vor sich gehen könnte.
perfekt ist nicht nur ein Profiler, sondern bietet auch Tracing-Unterstützung. Die Profilerstellung basiert auf dem Abtasten des Systemzustands, wenn dieser durch Hardware- oder Software-Leistungsindikatoren ausgelöst wird; es gibt eine statistische Auswahl von Punkten, an denen das System die meiste Zeit verbringt. Die Ablaufverfolgung nimmt stattdessen immer dann Stichproben, wenn ein bestimmtes Ablaufverfolgungsereignis auftritt, sodass sie für seltene, aber wichtige Ereignisse viel nützlicher ist.
Bei der Arbeit mit PostgreSQL eines der spannendsten Features von perf ist die Fähigkeit, User-Space-Prozesse zu verfolgen . Möchten Sie wissen, wie oft Ihr PostgreSQL WAL-Segmente austauscht, wie oft es Fremdschlüsselsuchen durchführt usw.? Für ein PostgreSQL-Backend oder für den gesamten Cluster? perfekt kann dabei helfen.
User-Space- und Kernel-Space-Tracepoints können gemischt und gleichzeitig als Performance Counter-Profiling verwendet werden, um Ihnen zu helfen, sich ein gutes Bild vom System zu machen. perfekt kann Stack-Traces sowohl aus dem Kernel als auch aus dem Benutzerbereich erfassen und kann auch statistische Visualisierungen durchführen. User-Space-Tracepoints werden mit dynamischen Sonden erstellt; solche aus dem Kernelbereich können vordefiniert oder dynamische Prüfpunkte sein.
Wie verwenden Sie also einige dieser Funktionen?
Installieren Sie die Tools
Stellen Sie zunächst sicher, dass Sie eine aktuelle perf verwenden . Dieser Artikel wurde auf Fedora 19 mit perf 3.11.6 geschrieben auf x86_64, und einige der Funktionen sind relativ neu.
Wenn Sie User-Space-Stack-Ergebnisse wünschen, sollten Sie den Code, den Sie sich ansehen, mit -Og -ggdb -fno-omit-frame-pointer erstellen . Wenn Sie ein perf verwenden gebaut mit libunwind Sie brauchen keine Frame-Zeiger; siehe diesen Stack Overflow-Post und RH Bugzilla #1025603. Nichts davon ist erforderlich, wenn Sie nur an Kernel-seitigen Daten interessiert sind. Wenn Sie Distributionspakete verwenden, müssen Sie möglicherweise -debuginfo installieren auch Pakete.
Alle folgenden Tests wurden mit standardmäßigen PGDG PostgreSQL 9.2-Paketen von http://yum.postgresql.org/ unter Verwendung von perf ausgeführt neu aufgebaut mit libunwind Support gemäß den obigen Anweisungen.
Kernel-Tracepoints und -Probes
perfekt kann Daten von vordefinierten Kernel-Tracepoints erfassen, von denen einige informativ sind, wenn es um Probleme mit Speicherfragmentierung, Festplatten-E/A usw. geht. Sie können eine Liste von Tracepoints mit sudo perf list abrufen . Tracepoint-Listen können angegeben werden und Wildcards werden unterstützt. Wenn wir zum Beispiel Schreib- und Festplatten-Flush-Statistiken für eine laufende PostgreSQL-Instanz erhalten möchten, könnten wir Folgendes ausführen:
sudo perf record -g dwarf -e block:block_rq_issue,syscalls:sys_enter_fsync -u postgres sleep 10
um die Daten zu erfassen. Anstelle von „sleep“ können Sie keinen Befehl verwenden und „ctrl-C“ drücken, wenn Sie mit der Aufnahme fertig sind, oder Sie können einen anderen Befehl wie psql -c verwenden um die Arbeitsbelastung auszulösen, die Sie messen möchten.
-u postgres Profile aller Prozesse, die als Benutzer postgres laufen . Sie können stattdessen -a verwenden für die Profilerstellung des gesamten Systems über alle CPUs hinweg. Es ist auch möglich, nur ein Backend zu verfolgen. Starten Sie psql , führen Sie select pg_backend_pid() aus , führen Sie perf aus mit -p $the_pid , und starten Sie dann die Arbeitslast in derselben psql Sitzung.
Wenn Sie mit PostgreSQL arbeiten, wird der Standardzielprozess, also der Befehl, unter der Kontrolle von perf ausgeführt , ist normalerweise nicht sehr nützlich, da das Backend die meiste Arbeit erledigt, nicht psql . Es ist immer noch nützlich, den Unterbefehl zu verwenden, um die Testarbeitslast und das Timing zu steuern.
Sobald Sie die Daten erfasst haben, können Sie den Leistungsbericht verwenden es zu untersuchen. Es gibt zu viele Optionen, um sie hier zu diskutieren – um die Ergebnisaggregation und -vereinfachung, die Stack-Trace-Anzeige, interaktive Flüche vs. die Ausgabe von Textberichten und mehr zu steuern.
Nehmen Sie diese Sitzung als Beispiel, wo es eine Shell-Sitzung (Terminal „T2“) und eine Postgres-Sitzung gibt, die mit der Datenbank „regress“ (Terminal „T1“) verbunden ist:
T1| regress=> pg_backend_pid();T1| auswählen pg_backend_pid T1| ----------------T1| 4495T1|(1 Zeile)
T2| $ sudo perf record -g dwarf -e block:block_rq_*,syscalls:sys_enter_write,syscalls:sys_enter_fsync -p 4495
T1| regress=> Tabelle x erstellen als select a FROM generate_series(1,1000000) a;T1| regress=>
T2| $ ^CT2| [ Leistungsdatensatz:332 Mal aufgewacht, um Daten zu schreiben ]T2| [ Leistungsdatensatz:Erfasst und geschrieben 86,404 MB perf.data (~3775041 Beispiele) ]T2|T2| $ sudo Leistungsbericht -g
Sie können den Leistungsbericht verwenden 's fluchen gui, um in den Trace einzudringen, oder Sie können den perf report --stdio verwenden Option, um Daten nach stdout zu streamen. Wenn Sie beispielsweise Stacktraces wünschen, könnten Sie Folgendes ausführen:
$ sudo perf report -g --stdio... bla bla ...# Beispiele:1 des Ereignisses 'syscalls:sys_enter_fsync'# Ereignisanzahl (ungefähr):1## Overhead Command Shared Object Symbol# .. ...... ........ ............. .....................# 100,00 % postgres libc-2.17.so [.] __GI___libc_fsync | --- __GI___libc_fsync mdimmedsync heap_sync intorel_shutdown standard_ExecutorRun ExecCreateTableAs PortalRunUtility PortalRunMulti PortalRun PostgresMain ServerLoop PostmasterMain main __libc_start_main _start (nil)... bla bla...
zeigt das für das Ereignis syscalls:sys_enter_fsync Es gab ein Ereignis mit dem obigen Stack, ein fsync, das über ExecCreateTableAs aufgerufen wurde .
(Aus einem bestimmten Grund konnte ich das endgültige fsync() noch nicht festlegen scheint von perf nicht erfasst zu werden wenn psql wird direkt unter der Kontrolle von perf ausgeführt . Dies ist kein Problem mit perf stat , nur perf record . Deshalb springe ich durch die Reifen, um das Backend per PID oben vorzuwählen.)
Dynamische User-Space-Sonden
Manchmal interessieren Sie sich mehr für etwas, das in PostgreSQL selbst passiert, als für Ereignisse im Kernel, die von PostgreSQL ausgelöst werden. Neuere Versionen von perf kann dabei helfen, indem es dynamische Tracepoints einfügt, die bei Aufrufen in User-Space-Programmen ausgelöst werden.
Angenommen, Sie möchten die WAL-Aktivität beobachten und sehen, wann XLogFlush , XLogFileInit oder XLogFileOpen werden genannt. Mit perf können Sie für diese Aufrufe dynamische Tracepoints einfügen :
sudo perf probe -x `welches postgres` XLogFileInitsudo perf probe -x `welches postgres` XLogFileOpensudo perf probe -x `welches postgres` XLogFlush
Sie können nur externe Symbole prüfen (nicht statisch, nicht durch -fvisibility-Flags versteckt), es sei denn, Sie haben mit -ggdb gebaut . perfekt beschwert sich keine Symbole gefunden wenn Sie versuchen, ein Symbol zu verwenden, das nicht existiert. Zum Zeitpunkt des Schreibens perf unterstützt nicht die Verwendung externer debuginfos zum Suchen von Symbolen für Sonden, kann sie jedoch für die Stapelanalyse verwenden. Im Allgemeinen, wenn es sich um eine externe Datei in src/include handelt Sie können es mit perf verwenden .
Jeder Tracepoint gibt den Namen des erstellten Tracepoints aus und Sie können perf probe -l verwenden um sie trotzdem alle aufzulisten:
$ sudo perf probe -l probe_postgres:XLogFileInit (auf 0x000000000009a360) probe_postgres:XLogFileOpen (auf 0x000000000009a860) probe_postgres:XLogFlush (auf 0x00000000000a0670)
Diese Sonden können jetzt als Leistungsereignisse verwendet werden. Werfen wir einen Blick auf die xlog-Aktivität während eines Beispiel-Workloads und überwachen den gesamten Cluster, während ich einen pgbench-Lauf durchführe:
sudo perf record -g dwarf -u postgres -e probe_postgres:XLogFileInit,probe_postgres:XLogFileOpen,probe_postgres:XLogFlush
Probieren Sie es selbst mit perf report -g aus . So sehen die Ergebnisse aus. Sie können Optionen wie -g fractal,0 verwenden Details zu kontrollieren. Sie können den Prozentsatz der Treffer eines bestimmten Zählers sehen, die von dem einen oder anderen Stack-Zweig, der PID und dem Prozess usw. kamen. Die --sort Optionen geben Ihnen mehr Kontrolle über Aggregation und Gruppierung.
Aber warte, es gibt noch mehr
Sie sollten sich auch die Leistungsstatistik ansehen und perf top Befehle. Sie können die gleichen Event-Listen wie perf record nehmen , obwohl ihre Unterstützung für Prozessfilter aus irgendeinem Grund anders ist.
Hier ist ein Beispiel, das eine Dummy-Workload ausführt und während der Ausführung I/O-Kernel-Tracepoints betrachtet:
$ sudo perf stat -e block:block_rq_*,syscalls:sys_enter_write,syscalls:sys_enter_fsync -a -r 5 -- psql -q -U postgres craig -c "Tabelle löschen, wenn x existiert; Tabelle x als Auswahl von a erstellen FROM generate_series(1,1000000) a;"; Leistungszählerstatistiken für 'psql -U postgres craig -c Tabelle löschen, falls x existiert; erstelle Tabelle x als select a FROM generate_series(1,1000000) a;' (5 Läufe):0 block:block_rq_abort [100,00 %] 0 block:block_rq_requeue [100,00 %] 97 block:block_rq_complete ( +- 14,82 % ) [100,00 %] 96 block:block_rq_insert ( +- 14,97 % ) [100,00 %] 98 block:block_rq_issue ( +- 14,67 % ) [100,00 %] 0 block:block_rq_remap [100,00 %]10.607 syscalls:sys_enter_write ( +- 0,17 % ) [100,00 %] 1 syscalls:sys_enter_fsync 0,908835058 Sekunden verstrichene Zeit ( +- 18,31 ) /pre>Sie können sehen, dass es durchschnittlich etwa 100 Block-Layer-I/O-Anforderungen über 10.000 Write()s und ein einzelnes fsync() ausführt. Einige davon sind Hintergrundgeräusche des Systems, da wir die gesamte Systemprofilerstellung durchführen (-a ), aber da das System ziemlich im Leerlauf ist, ist es nicht viel, und es wird über fünf Läufe gemittelt.
Behalten Sie auf ähnliche Weise die xlog-Aktivität während eines pgbench-Laufs im Auge, indem Sie die zuvor hinzugefügten dynamischen Sonden verwenden:
$ sudo perf stat -e probe_postgres:XLogFileInit,probe_postgres:XLogFileOpen,probe_postgres:XLogFlush -a -- /usr/pgsql-9.2/bin/pgbench -U postgres craig -c 2 -t 10000Starting vacuum...end. Transaktionstyp:TPC-B (Art von) Skalierungsfaktor:100 Abfragemodus:einfach Anzahl Clients:2 Anzahl Threads:1 Anzahl Transaktionen pro Client:10000 Anzahl tatsächlich verarbeiteter Transaktionen:20000/20000 tps =715,854663 (einschließlich Verbindungsaufbau) tps =716,092133 ( ohne Herstellung von Verbindungen) Leistungszählerstatistiken für „/usr/pgsql-9.2/bin/pgbench -U postgres craig -c 2 -t 10000“:64 probe_postgres:XLogFileInit [100,00 %] 0 probe_postgres:XLogFileOpen [100,00 %] 55.440 probe_postgres:XLogFlush 27,987364469 Sekunden verstrichene ZeitSie können noch viel mehr tun, einschließlich der Erfassung des Zustands lokaler Variablen mit perf probe . Ich werde später einige nützliche Beispiele dafür aufschreiben. In der Zwischenzeit können Sie mit einem neuen Diagnosetool spielen, erkunden und Spaß haben.
Aktualisierung: Michael Paquier hat kürzlich einen verwandten Artikel über das Tracing von PostgreSQL mit systemtap geschrieben, der für Leser dieses Artikels von Interesse sein könnte. Sie müssen Pg neu kompilieren, um diesen Ansatz zu verwenden, aber die Syntax ist schöner und bietet einige andere Vorteile.