PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Tracciare PostgreSQL con perf

L'utilità di profilatura perf fornito con il kernel Linux è estremamente utile per esaminare il comportamento a livello di sistema e multi-processo, ma fa molto di più della profilatura della CPU per cui viene spesso utilizzata. Probabilmente hai guardato perf top -az o perf top -u postgres output, ma questo è solo il minimo di ciò che può fare. (Se si desidera la versione TL/DR, passare a "Sonde dinamiche spaziali utente").

Uno dei grandi vantaggi di perf è che non è invadente. Non è necessario allegare un debugger e interrompere l'esecuzione. Non è necessario eseguire comandi direttamente sotto un profiler in un ambiente speciale. Non è necessario riavviare il server per eseguire il debug di un carico di lavoro problematico e spesso non è necessario ricompilare con le opzioni di debug. Questo è estremamente utile quando stai cercando di rintracciare problemi di prestazioni in un sistema live, in quanto ti consente di testare teorie su ciò che potrebbe accadere rapidamente e con un impatto minimo.

perfezione non è solo un profiler, ha anche il supporto per la traccia. La profilazione si basa sul campionamento dello stato del sistema quando attivato da contatori delle prestazioni hardware o software; fornisce un campionamento statistico dei punti in cui il sistema trascorre la maggior parte del tempo. La traccia invece preleva campioni ogni volta che si verifica un particolare evento di traccia, quindi è molto più utile per eventi rari ma importanti.

Quando si lavora con PostgreSQL, una delle funzionalità più interessanti di perf è la capacità di tracciare i processi nello spazio utente . Vuoi sapere con quale frequenza PostgreSQL scambia segmenti WAL, quanto spesso esegue ricerche di chiavi esterne, ecc.? Per un back-end PostgreSQL o per l'intero cluster? perfezione può aiutare in questo.

I punti di traccia dello spazio utente e dello spazio del kernel possono essere mischiati e possono essere utilizzati contemporaneamente al profilo del contatore delle prestazioni per aiutarti a ottenere una buona immagine del sistema. perfezione può acquisire tracce di stack sia dal kernel che dallo spazio utente e può anche eseguire visualizzazioni statistiche. I tracepoint dello spazio utente vengono creati con sonde dinamiche; quelli dello spazio kernel possono essere predefiniti o possono essere sonde dinamiche.

Allora, come usi alcune di queste funzionalità?

Installa gli strumenti

Innanzitutto, assicurati di utilizzare una perf corrente . Questo articolo è stato scritto su Fedora 19 con perf 3.11.6 su x86_64 e alcune delle funzionalità sono relativamente nuove.

Se vuoi risultati dello stack dello spazio utente, vorrai che il codice che stai guardando sia compilato con -Og -ggdb -fno-omit-frame-pointer . Se stai usando un perf costruito con libunwind non hai bisogno di frame-pointer; vedere questo post Stack Overflow e RH Bugzilla #1025603. Niente di tutto ciò è necessario se sei interessato solo ai dati lato kernel. Se stai usando pacchetti di distribuzione potresti dover installare -debuginfo anche i pacchetti.

Tutti i seguenti test sono stati eseguiti con pacchetti PGDG PostgreSQL 9.2 di serie da http://yum.postgresql.org/ utilizzando un perf ricostruito con libunwind supporto secondo le istruzioni di cui sopra.

Tracepoint e sonde del kernel

perfezione può acquisire dati da tracepoint del kernel predefiniti, alcuni dei quali sono informativi quando si esaminano problemi con la frammentazione della memoria, l'I/O del disco, ecc. È possibile ottenere un elenco di tracepoint con sudo perf list . È possibile specificare elenchi di tracepoint e sono supportati i caratteri jolly. Ad esempio, se vogliamo ottenere statistiche di scrittura e svuotamento del disco su un'istanza PostgreSQL in esecuzione, potremmo eseguire:

sudo perf record -g dwarf -e block:block_rq_issue,syscalls:sys_enter_fsync -u postgres sleep 10

per acquisire i dati. Invece di dormire non puoi usare nessun comando e premi control-C quando hai finito di catturare, oppure puoi usare qualche altro comando come un psql -c per attivare il carico di lavoro che desideri misurare.

-u postgres profila tutti i processi in esecuzione come utente postgres . Puoi invece usare -a per la profilazione dell'intero sistema su tutte le CPU. È anche possibile tracciare un solo back-end. Avvia psql , esegui select pg_backend_pid() , esegui perf con -p $the_pid , quindi avvia il carico di lavoro nello stesso psql sessione.

Quando lavori con PostgreSQL, il processo di destinazione predefinito, che è il comando eseguito sotto il controllo di perf , di solito non è molto utile perché il backend fa la maggior parte del lavoro, non psql . È comunque utile utilizzare il sottocomando per controllare il carico di lavoro del test e la tempistica.

Una volta acquisiti i dati, puoi utilizzare rapporto perf per esaminarlo. Ci sono troppe opzioni da discutere qui:per controllare l'aggregazione e la semplificazione dei risultati, la visualizzazione della traccia dello stack, le maledizioni interattive rispetto all'output di report di testo e altro ancora.

Prendi questa sessione come esempio, dove c'è una sessione di shell (terminale "T2") e una sessione postgres collegata al database "regress" (terminale "T1"):

T1| regress=> seleziona pg_backend_pid();T1| pg_backend_pid T1| ----------------T1| 4495T1|(1 riga)
T2| $ sudo perf record -g dwarf -e block:block_rq_*,syscalls:sys_enter_write,syscalls:sys_enter_fsync -p 4495
T1| regress=> crea la tabella x come seleziona a FROM generate_series(1,1000000) a;T1| regress=>
T2| $ ^CT2| [ record perf:svegliato 332 volte per scrivere i dati ]T2| [ record perf:catturato e scritto 86.404 MB perf.data (~3775041 campioni) ]T2|T2| $ sudo perf report -g

Puoi usare rapporto perf 's curses gui per approfondire la traccia, oppure puoi usare il report perf --stdio opzione per farlo trasmettere i dati in streaming a stdout. Ad esempio, se desideri tracciare lo stack potresti eseguire:

$ sudo perf report -g --stdio... blah blah ...# Esempi:1 dell'evento 'syscalls:sys_enter_fsync'# Conteggio eventi (approssimativo):1## Comando Overhead Simbolo oggetto condiviso# .. ...... ........ ............. .....................# 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)... blah blah...

mostrandolo per l'evento syscalls:sys_enter_fsync c'era un evento con lo stack sopra, un fsync invocato tramite ExecCreateTableAs .

(Per un motivo non sono ancora stato in grado di definire il fsync() finale non sembra essere stato catturato da perf quando psql viene eseguito direttamente sotto il controllo di perf . Questo non è un problema con perf stat , solo record perf . Ecco perché sto facendo i salti mortali per preselezionare il backend tramite pid sopra.)

Sonde dinamiche nello spazio utente

A volte sei più interessato a qualcosa che accade all'interno di PostgreSQL stesso rispetto agli eventi all'interno del kernel attivati ​​da PostgreSQL. Versioni più recenti di perf può aiutare con questo inserendo tracepoint dinamici che si attivano sulle chiamate nei programmi dello spazio utente.

Supponiamo che tu sia interessato a guardare l'attività WAL e desideri vedere quando XLogFlush , XLogFileInit o XLogFileOpen sono chiamati. Puoi inserire punti di traccia dinamici per queste chiamate con perf :

sudo perf probe -x `che postgres` XLogFileInitsudo perf probe -x `che postgres` XLogFileOpensudo perf probe -x `che postgres` XLogFlush

Puoi solo sondare simboli esterni (non statici, non nascosti da -fvisibility flag) a meno che tu non abbia compilato con -ggdb . perfezione si lamenterà nessun simbolo trovato se provi a usare un simbolo che non esiste. Nel momento in cui scrivo perf non supporta l'utilizzo di informazioni di debug esterne per cercare i simboli per le sonde, sebbene possa utilizzarlo per l'analisi dello stack. In generale, se è un esterno in src/include puoi usarlo con perf .

Ciascun tracepoint stamperà il nome del tracepoint creato ed è possibile utilizzare perf probe -l per elencarli tutti comunque:

$ sudo perf probe -l probe_postgres:XLogFileInit (su 0x000000000009a360) probe_postgres:XLogFileOpen (su 0x0000000000009a860) probe_postgres:XLogFlush (su 0x00000000000a0670)

Queste sonde sono ora utilizzabili come eventi perf. Diamo un'occhiata all'attività di xlog durante un carico di lavoro di esempio, monitorando l'intero cluster mentre eseguo pgbench:

sudo perf record -g dwarf -u postgres -e probe_postgres:XLogFileInit,probe_postgres:XLogFileOpen,probe_postgres:XLogFlush

Provalo tu stesso con report perf -g . Ecco come appaiono i risultati. Puoi usare opzioni come -g frattale,0 per controllare i dettagli. Sarai in grado di vedere la percentuale di hit di un determinato contatore provenienti da un ramo dello stack o da un altro, il pid e il processo, ecc. Il --sort le opzioni ti danno un maggiore controllo sull'aggregazione e il raggruppamento.

Ma aspetta, c'è di più

Dovresti anche controllare le statistiche perf e top perfetto comandi. Possono prendere gli stessi elenchi di eventi di record perf , anche se per qualche strana ragione il loro supporto per i filtri di processo è diverso.

Ecco un esempio che esegue un carico di lavoro fittizio ed esamina i tracepoint del kernel I/O durante l'esecuzione:

$ sudo perf stat -e block:block_rq_*,syscalls:sys_enter_write,syscalls:sys_enter_fsync -a -r 5 -- psql -q -U postgres craig -c "rilascia la tabella se esiste x; crea la tabella x come seleziona a DA generate_series(1,1000000) a;"; Statistiche del contatore delle prestazioni per 'psql -U postgres craig -c drop table se esiste x; crea la tabella x come seleziona a FROM generate_series(1,1000000) a;' (5 esecuzioni):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 secondi tempo trascorso ( +- 18.31%) /pre> 

Puoi vedere che sta eseguendo una media di circa 100 richieste di I/O a livello di blocchi su 10k write() e facendo un singolo fsync(). Alcuni di questi sono rumori di fondo del sistema poiché stiamo eseguendo tutta la profilazione del sistema (-a ), ma poiché il sistema è abbastanza inattivo, non è molto e la media è di cinque esecuzioni.

Allo stesso modo, usando le sonde dinamiche che abbiamo aggiunto in precedenza, tieni d'occhio l'attività di xlog durante un'esecuzione di pgbench:

$ 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. tipo di transazione:TPC-B (sort of)fattore di scala:100modalità query:semplicenumero di client:2numero di thread:1numero di transazioni per client:10000numero di transazioni effettivamente elaborate:20000/20000tps =715.854663 (incluse connessioni che stabiliscono)tps =716.092133 ( esclusa la creazione di connessioni) Statistiche del contatore delle prestazioni per '/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 secondi di tempo trascorso

C'è molto di più che puoi fare, inclusa l'acquisizione dello stato delle variabili locali con perf probe . Scriverò alcuni esempi utili di quello più tardi. Nel frattempo, gioca, esplora e divertiti con un nuovo strumento diagnostico.

Aggiornamento: Michael Paquier ha recentemente scritto un articolo correlato sulla traccia di PostgreSQL con systemtap che potrebbe interessare i lettori di questo. Devi ricompilare Pg per usare quell'approccio, ma la sintassi è migliore e offre altri vantaggi.