PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Rastreando PostgreSQL com perf


O utilitário de criação de perfil perf que vem com o kernel do Linux é extremamente útil para examinar o comportamento de todo o sistema e de vários processos - mas faz muito mais do que o perfil da CPU para o qual é frequentemente usado. Você provavelmente já viu perf top -az ou perf top -u postgres saída, mas isso é apenas um pouco do que ele pode fazer. (Se você quiser a versão TL/DR, vá para “Probes dinâmicas do espaço do usuário”).

Uma das grandes vantagens do perf é que não é intrusivo. Você não precisa anexar um depurador e interromper a execução. Você não precisa executar comandos diretamente em um criador de perfil em um ambiente especial. Não há necessidade de reiniciar o servidor para depurar uma carga de trabalho problemática e, muitas vezes, não há necessidade de recompilar com opções de depuração. Isso é extremamente útil quando você está tentando rastrear problemas de desempenho em um sistema ativo, pois permite testar teorias sobre o que pode estar acontecendo rapidamente e com impacto mínimo.

perfeito não é apenas um criador de perfil, ele também tem suporte para rastreamento. A criação de perfil é baseada na amostragem do estado do sistema quando acionado por contadores de desempenho de hardware ou software; fornece uma amostragem estatística dos pontos onde o sistema passa a maior parte do tempo. O rastreamento, em vez disso, coleta amostras sempre que um determinado evento de rastreamento ocorre, portanto, é muito mais útil para eventos pouco frequentes, mas importantes.

Ao trabalhar com o PostgreSQL, um dos recursos mais interessantes do perf é a capacidade de rastrear processos no espaço do usuário . Quer saber com que frequência seu PostgreSQL está trocando segmentos WAL, com que frequência ele faz pesquisas de chave estrangeira, etc? Para um back-end do PostgreSQL ou em todo o cluster? perfeito pode ajudar com isso.

Pontos de rastreamento de espaço de usuário e espaço de kernel podem ser combinados e usados ​​ao mesmo tempo que a criação de perfil do contador de desempenho para ajudá-lo a obter uma boa imagem do sistema. perfeito pode capturar rastreamentos de pilha do kernel e do espaço do usuário e também pode fazer visualizações estatísticas. Os pontos de rastreamento do espaço do usuário são criados com testes dinâmicos; os de espaço do kernel podem ser pré-definidos ou podem ser testes dinâmicos.

Então, como você usa alguns desses recursos?

Instale as ferramentas


Primeiro, verifique se você está usando um perf atual . Este artigo foi escrito no Fedora 19 com perf 3.11.6 em x86_64, e alguns dos recursos são relativamente novos.

Se você quiser resultados de pilha de espaço de usuário, você vai querer que o código que você está olhando seja construído com -Og -ggdb -fno-omit-frame-pointer . Se você estiver usando um perf construído com libunwind você não precisa de ponteiros de quadro; veja este post do Stack Overflow e RH Bugzilla #1025603. Nada disso é necessário se você estiver interessado apenas em dados do lado do kernel. Se você estiver usando pacotes de distribuição, talvez seja necessário instalar -debuginfo pacotes também.

Todos os testes a seguir foram executados com pacotes PGDG PostgreSQL 9.2 padrão de http://yum.postgresql.org/ usando um perf reconstruído com libunwind suporte de acordo com as instruções acima.

Pontos de rastreamento e sondas do kernel


perfeito pode capturar dados de pontos de rastreamento de kernel predefinidos, alguns dos quais são informativos ao analisar problemas com fragmentação de memória, E/S de disco, etc. Você pode obter uma lista de pontos de rastreamento com sudo perf list . As listas de pontos de rastreamento podem ser especificadas e os curingas são suportados. Por exemplo, se quisermos obter estatísticas de gravação e liberação de disco em uma instância do PostgreSQL em execução, podemos executar:
sudo perf record -g dwarf -e block:block_rq_issue,syscalls:sys_enter_fsync -u postgres sleep 10

para capturar os dados. Em vez de dormir, você não pode usar nenhum comando e pressionar control-C quando terminar de capturar, ou pode usar algum outro comando como psql -c para acionar a carga de trabalho que você deseja medir.

-u postgres perfila todos os processos rodando como usuário postgres . Você pode usar -a para perfis de todo o sistema em todas as CPUs. Também é possível rastrear apenas um back-end. Inicie o psql , execute select pg_backend_pid() , execute perf com -p $the_pid , então inicie a carga de trabalho no mesmo psql sessão.

Quando você está trabalhando com o PostgreSQL, o processo alvo padrão, que é o comando executado sob o controle de perf , geralmente não é muito útil porque o backend faz a maior parte do trabalho, não o psql . Ainda é útil usar o subcomando para controlar a carga de trabalho e o tempo de teste.

Depois de capturar os dados, você pode usar o relatório de desempenho para examiná-lo. Há muitas opções para discutir aqui – para controlar a agregação e simplificação de resultados, exibição de rastreamento de pilha, maldições interativas versus saída de relatório de texto e muito mais.

Tome esta sessão como exemplo, onde há uma sessão shell (terminal “T2”) e uma sessão postgres conectada ao banco de dados “regress” (terminal “T1”):
T1| regress=> selecione pg_backend_pid();T1| pg_backend_pid T1| ----------------T1| 4495T1|(1 linha)
T2| $ sudo perf record -g dwarf -e block:block_rq_*,syscalls:sys_enter_write,syscalls:sys_enter_fsync -p 4495
T1| regress=> crie a tabela x como selecione um FROM generate_series(1,1000000) a;T1| regress=>
T2| $ ^CT2| [ registro perf:Acordado 332 vezes para gravar dados ]T2| [ registro perf:Capturado e gravado 86.404 MB perf.data (~3775041 samples) ]T2|T2| $ sudo perf report -g

Você pode usar o relatório de desempenho 's curses gui para se aprofundar no rastreamento, ou você pode usar o perf report --stdio opção para fazê-lo transmitir dados para stdout. Por exemplo, se você quiser rastreamentos de pilha, poderá executar:
$ sudo perf report -g --stdio... blah blah ...# Exemplos:1 do evento 'syscalls:sys_enter_fsync'# Contagem de eventos (aprox.):1## Símbolo de objeto compartilhado de comando de sobrecarga# .. ...... ........ .................. ........................# 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...

mostrando isso para o evento syscalls:sys_enter_fsync havia um evento com a pilha acima, um fsync invocado via ExecCreateTableAs .

(Por uma razão, ainda não consegui definir o fsync() final não parece ser capturado por perf quando psql é executado diretamente sob o controle de perf . Este não é um problema com perf stat , apenas registro de desempenho . É por isso que estou pulando pelos aros para pré-selecionar o back-end pelo pid acima.)

Probes dinâmicos do espaço do usuário


Às vezes você está mais interessado em algo acontecendo dentro do PostgreSQL do que eventos dentro do kernel que são acionados pelo PostgreSQL. Versões mais recentes de perf pode ajudar com isso inserindo pontos de rastreamento dinâmicos que são acionados em chamadas em programas de espaço do usuário.

Digamos que você esteja interessado em assistir a atividade do WAL e queira ver quando XLogFlush , XLogFileInit ou XLogFileOpen são chamados. Você pode inserir pontos de rastreamento dinâmicos para essas chamadas com perf :
sudo perf probe -x `which postgres` XLogFileInitsudo perf probe -x `which postgres` XLogFileOpensudo perf probe -x `which postgres` XLogFlush

Você só pode testar símbolos externos (não estáticos, não ocultos por sinalizadores -fvisibility), a menos que tenha construído com -ggdb . perfeito irá reclamar nenhum símbolo encontrado se você tentar usar um símbolo que não existe. No momento da escrita perf não suporta o uso de informações de depuração externas para procurar símbolos para testes, embora possa usá-lo para análise de pilha. Em geral, se for um externo em src/include você pode usá-lo com perf .

Cada tracepoint imprimirá o nome do tracepoint criado e você pode usar perf probe -l para listá-los todos de qualquer maneira:
$ sudo perf probe -l probe_postgres:XLogFileInit (em 0x000000000009a360) probe_postgres:XLogFileOpen (em 0x000000000009a860) probe_postgres:XLogFlush (em 0x00000000000a0670)

Esses testes agora podem ser usados ​​como eventos de desempenho. Vamos dar uma olhada na atividade do xlog durante uma carga de trabalho de amostra, monitorando em todo o cluster enquanto faço uma execução do pgbench:
sudo perf record -g dwarf -u postgres -e probe_postgres:XLogFileInit,probe_postgres:XLogFileOpen,probe_postgres:XLogFlush

Experimente você mesmo com perf report -g . Veja como ficam os resultados. Você pode usar opções como -g fractal,0 para controlar detalhes. Você poderá ver a porcentagem de acertos de um determinado contador que vieram de uma ramificação da pilha ou de outra, o pid e o processo etc. O --sort as opções oferecem mais controle sobre agregação e agrupamento.

Mas espere, tem mais


Você também deve verificar o perf stat e melhor desempenho comandos. Eles podem usar as mesmas listas de eventos que registro de desempenho , embora por algum motivo estranho o suporte ao filtro de processo seja diferente.

Aqui está um exemplo que executa uma carga de trabalho fictícia e analisa os pontos de rastreamento do kernel de E/S durante a execução:
$ sudo perf stat -e block:block_rq_*,syscalls:sys_enter_write,syscalls:sys_enter_fsync -a -r 5 -- psql -q -U postgres craig -c "soltar tabela se existir x; criar tabela x como selecionar um FROM generate_series(1,1000000) a;"; Estatísticas do contador de desempenho para 'psql -U postgres craig -c drop table if exist x; crie a tabela x como selecione um FROM generate_series(1,1000000) a;' (5 execuções):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 segundos de tempo decorrido ( +- 18,31% ) /pré> 
Você pode ver que está fazendo uma média de cerca de 100 solicitações de E/S de camada de bloco em mais de 10 mil write()s e fazendo um único fsync(). Parte disso é ruído de fundo do sistema, já que estamos fazendo toda a criação de perfil do sistema (-a ), mas como o sistema está bastante ocioso, não é muito, e a média é calculada em cinco execuções.

Da mesma forma, usando os testes dinâmicos que adicionamos anteriormente, fique de olho na atividade do xlog durante uma execução do 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 vacuo...end. tipo de transação:TPC-B (tipo de)fator de escala:100modo de consulta:simplesnúmero de clientes:2número de threads:1número de transações por cliente:10000número de transações realmente processadas:20000/20000tps =715,854663 (incluindo estabelecimento de conexões)tps =716,092133 ( excluindo o estabelecimento de conexões) Estatísticas do contador de desempenho para '/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 segundos de tempo decorrido

Há muito mais que você pode fazer, incluindo capturar o estado de variáveis ​​locais com perf probe . Vou escrever alguns exemplos úteis disso mais tarde. Enquanto isso, brinque, explore e divirta-se com uma nova ferramenta de diagnóstico.

Atualização: Michael Paquier recentemente escreveu um artigo relacionado sobre rastreamento do PostgreSQL com systemtap que pode ser de interesse dos leitores deste. Você precisa recompilar o Pg para usar essa abordagem, mas a sintaxe é melhor e oferece algumas outras vantagens.