Linux Enhanced BPF (eBPF) Tracing Tools
Ferramentas de rastreamento BPF aprimoradas do Linux (eBPF)
Esta pågina mostra exemplos de ferramentas de anålise de desempenho usando aprimoramentos para o BPF (Berkeley Packet Filter) que foram adicionados aos kernels da sÊrie Linux 4.x, permitindo que o BPF faça muito mais do que apenas pacotes de filtragem. Esses aprimoramentos permitem que os programas de anålise personalizados sejam executados no rastreamento dinâmico do Linux, no rastreamento eståtico e nos eventos de criação de perfil.
O eBPF possui recursos de rastreamento sem fio semelhantes aos de DTrace e SystemTap, e jĂĄ usei muitas das minhas ferramentas do DTraceToolkit para o eBPF. Ă adequado para responder perguntas como:
- Todas as operaçþes ext4 demoram mais de 50 ms?
- O que ĂŠ executar a latĂŞncia da fila, como um histograma?
- Quais pacotes e aplicativos estĂŁo com retransmissĂľes TCP? Trace de forma eficiente (sem rastrear envio / recebimento).
- Qual ĂŠ o rastreamento da pilha quando os segmentos bloqueiam (fora da CPU) e quanto tempo eles bloqueiam?
EBPF tambÊm pode ser usado para módulos de segurança e redes definidas por software. Eu não estou cobrindo aqueles aqui (ainda assim, de qualquer maneira). Observe tambÊm: eBPF Ê chamado de apenas "BPF", especialmente em lkml.
ConteĂşdo da pĂĄgina:
Existem diferentes front-ends para eBPF, com bcc o mais popular. Nesta pĂĄgina, descreverei eBPF, bcc e demonstrei algumas das ferramentas de rastreamento que desenvolvi.
1. Captura de tela
Começando com uma captura de tela, aqui estå um exemplo de rastreamento e exibição de E / S de bloco (disco) como um mapa de calor de latência:
Eu adicionei algumas anotaçþes a essa captura de tela. Se você Ê novo nesta visualização, veja minha pågina em mapas de calor de latência .
Isso usa o rastreamento dinâmico do kernel (kprobes) para as funçþes do instrumento para o problema e a conclusão das E / S do dispositivo de bloco. Os programas eBPF personalizados são executados quando estes kprobes são atingidos, que gravam carimbos de data / hora na questão de E / S, recuperam-nas na conclusão, calculam o tempo delta e, em seguida, armazenam isso em um histograma de log 2. O programa do espaço do usuårio lê essa matriz de histograma periodicamente, uma vez por segundo, e desenha o mapa de calor. O resumo Ê feito no contexto do kernel, para eficiência.
2. One Liners
One-liners Ăşteis usando as ferramentas bcc (eBPF):
Ferramentas de uso Ăşnico
# Trace novos processos: Execsnoop # O arquivo de rastreamento abre com o processo e o nome do arquivo: Opensnoop # Resumir latência de bloqueio de E / S (disco) como uma distribuição de poder de 2 por disco: Biolatência -D # Resumir o tamanho da E / S do bloco como uma distribuição de poder de 2 pelo nome do programa: tamanho da mordida # Trace operaçþes comuns do sistema de arquivos ext4 com menos de 1 milissegundo: Ext4slower 1 # Trace TCP conexþes ativas (connect ()) com endereço IP e portas: Tcpconnect # Trace TCP passive connections (accept ()) com endereço IP e portas: Tcpaccept # Trace conexþes TCP para a porta local 80, com duração da sessão: Tcplife -L 80 # Trace TCP retransmissþes com endereços IP e estado TCP: Tcpretrans # Testes de pilha de amostra a 49 Hertz por 10 segundos, emite formato dobrado (para gråficos de chama): Perfil -fd -F 49 10 # Trace detalhes e latência das pesquisas de DNS do resolvedor: Gethostlatency # Comandos de rastreamento emitidos em todos os shells bash: Linha de base
Multi Tools: Kernel Dynamic Tracing
# Contagem "tcp_send *" função do kernel, saĂda de impressĂŁo a cada segundo: Funccount -i 1 'tcp_send *' # Count "vfs_ *" chama PID 185: Funccount -p 185 'vfs_ *' # Nomes de arquivo de rastreio abertos, usando o rastreamento dinâmico da função do_sys_open do kernel (): Trace 'p :: do_sys_open "% s", arg2' # Igual a antes ("p :: ĂŠ assumido se nĂŁo for especificado): Trace 'do_sys_open "% s", arg2' # Trace o retorno do kernel do_sys_open () funciton e imprima o retval: Trace 'r :: do_sys_open "ret:% d", retval' # Trace do_nanosleep () função do kernel e o segundo argumento (modo), com os rastreios da pilha do kernel: Traçar -K 'do_nanosleep "modo:% d", arg2' # Trace o modo do_nanosleep () fornecendo o protĂłtipo (nĂŁo ĂŠ necessĂĄrio debuginfo): Trace 'do_nanosleep (struct hrtimer_sleeper * t, modo enum hrtimer_mode) "mode:% d", mode' # Trace do_nanosleep () com o endereço da tarefa (pode ser NULL), observando a desreferĂŞncia: Trace 'do_nanosleep (struct hrtimer_sleeper * t, enum hrtimer_mode mode) "tarefa:% x", t> tarefa " # Contagem de frequĂŞncia tcp_sendmsg () tamanho: Argdist -C 'p :: tcp_sendmsg (struct sock * sk, struct msghdr * msg, size_t size): u32: tamanho' # Resumir o tamanho do tcp_sendmsg () como um histograma de poder de 2: Argdist -H 'p :: tcp_sendmsg (struct sock * sk, struct msghdr * msg, tamanho tamanho_t): u32: tamanho' # Rastreios de pilha de contagem de frequĂŞncia que levam Ă função submit_bio () (problema I / O do disco): Stackcount submit_bio # Resumir a latĂŞncia (tempo gasto) pela função vfs_read () para PID 181: Funclatency -p 181 -u vfs_read
Ferramentas mĂşltiplas: rastreamento dinâmico de nĂvel de usuĂĄrio
# Trace a função de biblioteca libc nanosleep () e imprima os detalhes do sono solicitado: Trace 'p: c: nanosleep (struct timespec * req) "% d sec% d nsec", req-> tv_sec, req-> tv_nsec' # Contar a chamada libc write () para PID 181 por descritor de arquivo: Argdist -p 181 -C 'p: c: write (int fd): int: fd' # Resumir a latência (tempo gasto) por libc getaddrinfo (), como um histograma de power-of-2 em microssegundos: Funclatency.py -u 'c: getaddrinfo'
Multi Tools: Kernel Static Tracing
# Conheça os rastreios de pilha que levaram a E / S do bloco emissor, rastreando seu ponto de sinalização do kernel:
Stackcount t: bloco: block_rq_insert
Em construção...
Ferramentas mĂşltiplas: rastreamento estĂĄticamente definido pelo usuĂĄrio (USDT)
# Trace a sonda pthread_create USDT e imprima arg1 como hexadecimal:
Trace 'u: pthread: pthread_create "% x", arg1'
Em construção...
Estes one-liners demonstram vĂĄrios recursos do bcc / eBPF. VocĂŞ tambĂŠm pode imprimir isso como uma cheatsheet.
3. Apresentação
Uma conversa recente sobre ferramentas de rastreamento eBPF no LCA 2017 ( slideshare , youtube ):
Outras apresentaçþes:
- MĂĄquina virtual BPF-in-kernel (slides PDF) por Alexei Starovoitov, Linux Collaboration Summit, 2015.
- Desempenho do Linux 4.x: Usando o BPF Superpowers (slides & video) por Brendan Gregg na conferĂŞncia Performance @ Scale do Facebook, 2016.
- EBPF Trace do Kernel para o espaço do usuårio (slides) por Gary Lin para o dia da tecnologia de compartilhamento, 2016
- Meet-cute entre eBPF e Kernel Tracing (slides) de Viller Hsiao, 2016.
- Olhando para o eBPF Abyss (slides) por Sasha Goldshtein para SREcon Europe 2016.
- Ferramentas de rastreamento do Linux 4.x: usando Superpowers BPF, de Brendan Gregg no USENIX LISA 2016 ( slideshare , PDF ). Incluiu my DĂŞ-me 15 minutos e mudarei sua visĂŁo do demo de rastreamento do Linux .
4. eBPF
O BPF se originou como uma tecnologia para otimizar filtros de pacotes. Se você executar o tcpdump com uma expressão (combinando em um host ou porta), ele Ê compilado em um bytecode BPF ótimo, que Ê executado por uma måquina virtual com sandboxs no kernel. O BPF avançado (tambÊm conhecido como eBPF, mas apenas o BPF) ampliou o que esta måquina virtual BPF poderia fazer: permitindo que ele funcionasse em eventos que não sejam pacotes e outras açþes alÊm de filtragem.
O eBPF pode ser usado para redes definidas por software, mitigação de DDoS (queda inicial de pacotes), melhorando o desempenho da rede (eXpress Data Path), detecção de intrusão e muito mais. Nesta pågina, estou focando seu uso em ferramentas de observabilidade, onde Ê usado como mostrado no seguinte fluxo de trabalho:
Nossa ferramenta de observabilidade possui o código BPF para executar determinadas açþes: medir a latência, resumir como um histograma, pegar traços de pilha, etc. Esse código BPF Ê compilado para o código de byte BPF e depois enviado para o kernel, onde um verificador pode rejeitå-lo se for Considerado inseguro (que inclui não permitir loops ou ramos para trås). Se o bytecode BPF for aceito, ele poderå ser anexado a diferentes fontes de eventos:
- Kprobes : rastreamento dinâmico do kernel.
- Enrugamentos : rastreamento dinâmico do nĂvel do usuĂĄrio.
- Pontos de rastreamento : rastreamento estĂĄtico do kernel.
- Perf_events : amostragem cronometrada e PMCs.
O programa BPF tem duas maneiras de passar dados medidos de volta para o espaço do usuĂĄrio: por detalhes do evento ou por um mapa BPF. Os mapas BPF podem implementar arrays, matrizes associativas e histogramas, e sĂŁo adequados para passar estatĂsticas de resumo.
4.1. PrĂŠ-requisitos
Um kernel do Linux compilado com CONFIG_BPF_SYSCALL (por exemplo, o Ubuntu faz isso) e pelo menos o kernel 4.4 (por exemplo, Ubuntu Xenial) para que o histograma, a estatĂstica e o rastreamento por evento sejam suportados. O diagrama a seguir mostra outros recursos com a versĂŁo Linux eBPF suportada chegou em verde:
5. bcc
A Coleção BPF Compiler estå em github.com/iovisor/bcc e fornece uma grande coleção de ferramentas de exemplos de rastreamento, bem como interfaces Python e lua para desenvolvê-las. O diagrama no canto superior direito desta pågina ilustra estas ferramentas bcc.
Os prÊ-requisitos são iguais ao eBPF acima, e Python. Se você estiver em um kernel antigo (entre 4.1 e 4.8) e a ferramenta bcc que deseja executar não funciona, veja as ferramentas / diretório antigo do bcc, que podem ter uma versão legada que emprega soluçþes alternativas.
O cĂłdigo de rastreamento de exemplo pode ser encontrado no diretĂłrio bcc / examples / tracing e incluĂdo no /docs/tutorial_bcc_python_developer.md. As ferramentas, sob / diretĂłrio de ferramentas, tambĂŠm podem servir como exemplos. Cada ferramenta tambĂŠm tem um exemplo de arquivo .txt em / tools e uma pĂĄgina de manual em / man / man8.
5.1. Instalação
Veja as instruçþes de instalação do bcc para começar em distros diferentes do Linux. Aqui estão as instruçþes do Ubuntu recentes, como um exemplo:
# Echo "deb [trust = yes] https://repo.iovisor.org/apt/xenial xenial-nightly main" | \ Sudo tee /etc/apt/sources.list.d/iovisor.list # sudo apt-get update # sudo apt-get install bcc-tools
As ferramentas bcc serĂŁo instaladas em / usr / share / bcc / tools.
5.2. Lista de verificação de desempenho geral
Esta lista de verificação pode ser útil se você não sabe por onde começar. Ele roteia vårias ferramentas bcc para analisar diferentes alvos, que podem desenterrar a atividade que você desconhecia anteriormente. Primeiro incluà isso no tutorial bcc , depois de uma lista de verificação de ferramentas padrão do Linux. Supþe-se que você tenha executado esses conceitos båsicos (dmesg, vmstat, iostat, top, etc.) e agora quer escavar mais fundo.
1. execsnoop
Trace novos processos via exec () syscalls e imprima o nome do processo pai e outros detalhes:
# Execsnoop PCOMM PID RET ARGS Bash 15887 0 / usr / bin / man ls PrĂŠconv ââ15894 0 / usr / bin / preconv -e UTF-8 Homem 15896 0 / usr / bin / tbl Homem 15897 0 / usr / bin / nroff -mandoc -rLL = 169n -rLT = 169n -Tutf8 Homem 15898 0 / usr / bin / pager -s Nroff 15900 0 / usr / bin / locale charmap Nroff 15901 0 / usr / bin / groff -mtty-char -Tutf8 -mandoc -rLL = 169n -rLT = 169n Groff 15902 0 / usr / bin / troff -mtty-char -mandoc -rLL = 169n -rLT = 169n -Tutf8 Groff 15903 0 / usr / bin / grotty [...]
2. opensnoop
Trace open () syscalls e nome do processo de impressĂŁo e detalhes do nome do caminho:
# Opensnoop PID COMM FD ERR PATH 27159 catalina.sh 3 0 /apps/tomcat8/bin/setclasspath.sh 4057 redis-server 5 0 / proc / 4057 / stat 2360 redis-server 5 0 / proc / 2360 / stat 30668 sshd 4 0 / proc / sys / kernel / ngroups_max 30668 sshd 4 0 / etc / group 30668 sshd 4 0 /root/.ssh/authorized_keys 30668 sshd 4 0 /root/.ssh/authorized_keys 30668 sshd -1 2 / var / run / nologin 30668 sshd -1 2 / etc / nologin 30668 sshd 4 0 /etc/login.defs 30668 sshd 4 0 / etc / passwd 30668 sshd 4 0 / etc / shadow 30668 sshd 4 0 / etc / localtime 4510 snmp-pass 4 0 / proc / cpuinfo [...]
3. ext4slower
Trace as operaçþes lentas do ext4 que são mais lentas do que um limite fornecido (o bcc possui versþes deste para btrfs, XFS e ZFS tambÊm):
# Ext4slower 1 Rastreando operaçþes ext4 com menos de 1 ms TIME COMM PID T BYTES OFF_KB LAT (ms) FILENAME 06:49:17 bash 3616 R 128 0 7,75 cksum 06:49:17 cksum 3616 R 39552 0 1.34 [ 06:49:17 cksum 3616 R 96 0 5,36 2 a 3-2,7 06:49:17 cksum 3616 R 96 0 14,94 2to3-3.4 06:49:17 cksum 3616 R 10320 0 6.82 411toppm 06:49:17 cksum 3616 R 65536 0 4.01 a2p 06:49:17 cksum 3616 R 55400 0 8.77 ab 06:49:17 cksum 3616 R 36792 0 16.34 aclocal-1.14 06:49:17 cksum 3616 R 15008 0 19,31 acpi_listen 06:49:17 cksum 3616 R 6123 0 17.23 add-apt-repository 06:49:17 cksum 3616 R 6280 0 18.40 addpart 06:49:17 cksum 3616 R 27696 0 2.16 addr2line 06:49:17 cksum 3616 R 58080 0 10,11 ag
4. biolatĂŞncia
Resumir a latĂŞncia de E / S do dispositivo de bloco como um histograma a cada segundo:
# Biolatência -mT 1 Rastreamento do dispositivo do bloco I / O ... Pressione Ctrl-C para finalizar. 21:33:40 Msecs: distribuição de contagem 0 -> 1: 69 | ******************************************** 2 -> 3: 16 | ********* | 4 -> 7: 6 | *** | 8 -> 15: 21 | ************ | 16 -> 31: 16 | ********* | 32 -> 63: 5 | ** | 64 -> 127: 1 | | 21:33:41 Msecs: distribuição de contagem 0 -> 1: 60 | ************************ | 2 -> 3: 100 | *********************************************** 4 -> 7: 41 | **************** | 8 -> 15: 11 | **** | 16 -> 31: 9 | *** | 32 -> 63: 6 | ** | 64 -> 127: 4 | * | 21:33:42 Msecs: distribuição de contagem 0 -> 1: 110 | ********************************************* 2 -> 3: 78 | ******************************** 4 -> 7: 64 | *********************** | 8 -> 15: 8 | ** | 16 -> 31: 12 | **** | 32 -> 63: 15 | ***** | 64 -> 127: 8 | ** | [...]
5. biosnoop
E / S do dispositivo de bloco de rastreamento com detalhes de processo, disco e latĂŞncia:
# Biosnoop TEMPO (s) COMM PID DISK T SETOR BYTES LAT (ms) 0.000004001 supervisionar 1950 xvda1 W 13092560 4096 0.74 0.000178002 supervisionar 1950 xvda1 W 13092432 4096 0.61 0.001469001 supervisionar 1956 xvda1 W 13092440 4096 1.24 0.001588002 supervisionar 1956 xvda1 W 13115128 4096 1.09 1.022346001 supervisionar 1950 xvda1 W 13115272 4096 0.98 1.022568002 supervisionar 1950 xvda1 W 13188496 4096 0.93 1.023534000 supervisionar 1956 xvda1 W 13188520 4096 0.79 1.023585003 supervisionar 1956 xvda1 W 13189512 4096 0.60 2.003920000 xfsaild / md0 456 xvdc W 62901512 8192 0.23 2.003931001 xfsaild / md0 456 xvdb W 62901513 512 0.25 2.004034001 xfsaild / md0 456 xvdb W 62901520 8192 0.35 2.004042000 xfsaild / md0 456 xvdb W 63542016 4096 0.36 2.004204001 kworker / 0: 3 26040 xvdb W 41950344 65536 0.34 2.044352002 supervisionar 1950 xvda1 W 13192672 4096 0.65 [...]
6. cachestat
Mostra a proporção e o tamanho do hit / falta de cache da pågina e resuma todos os segundos:
# Cachestat HITS MISSES DIRTIES READ_HIT% WRITE_HIT% BUFFERS_MB CACHED_MB 170610 41607 33 80,4% 19,6% 11 288 157693 6149 33 96,2% 3,7% 11 311 174483 20166 26 89,6% 10,4% 12 389 434778 35 40 100,0% 0,0% 12 389 435723 28 36 100,0% 0,0% 12 389 846183 83800 332534 55,2% 4,5% 13 553 96387 21 24 100,0% 0,0% 13 553 120258 29 44 99,9% 0,0% 13 553 255861 24 33 100,0% 0,0% 13 553 191388 22 32 100,0% 0,0% 13 553 [...]
7. tcpconnect
Trace TCP conexĂľes ativas (connect ()):
# Tcpconnect PID COMM IP SADDR DADDR DPORT 25333 recordProgra 4 127.0.0.1 127.0.0.1 28527 25338 curl 4 100.66.3.172 52.22.109.254 80 25340 curl 4 100.66.3.172 31.13.73.36 80 25342 curl 4 100.66.3.172 104.20.25.153 80 25344 curl 4 100.66.3.172 50.56.53.173 80 25365 recordProgra 4 127.0.0.1 127.0.0.1 28527 26119 ssh 6 :: 1 :: 1 22 25388 recordProgra 4 127.0.0.1 127.0.0.1 28527 25220 ssh 6 fe80: 8a3: 9dff: fed5: 6b19 fe80 :: 8a3: 9dff: fed5: 6b19 22 [...]
8. tcpaccept
Trace conexĂľes passivas TCP (accept ()):
# Tcpaccept PID COMM IP RADDR LADDR LPORT 2287 sshd 4 11.16.213.254 100.66.3.172 22 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 2287 sshd 6 :: 1 :: 1 22 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 2287 sshd 6 fe80 :: 8a3: 9dff: fed5: 6b19 fe80 :: 8a3: 9dff: fed5: 6b19 22 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 [...]
9. tcpretrans
Transtornos TCP retransmissĂveis e TLPs:
# Tcpretrans TIME PID IP LADDR: LPORT T> RADDR: ESTADO DE RUA 01:55:05 0 4 10.153.223.157:22 R> 69.53.245.40:34619 ESTABELECIDO 01:55:05 0 4 10.153.223.157:22 R> 69.53.245.40:34619 ESTABELECIDO 01:55:17 0 4 10.153.223.157:22 R> 69.53.245.40:22957 ESTABELECIDO [...]
10. gethostlatency
Mostrar latĂŞncia para getaddrinfo / gethostbyname [2] chamadas de biblioteca, em todo o sistema:
# Gethostlatency TIME PID COMM LATms HOST 06:10:24 28011 wget 90.00 www.iovisor.org 06:10:28 28127 wget 0.00 www.iovisor.org 06:10:41 28404 wget 9.00 www.netflix.com 06:10:48 28544 curl 35.00 www.netflix.com.au 06:11:10 29054 curl 31.00 www.plumgrid.com 06:11:16 29195 curl 3.00 www.facebook.com 06:11:24 25313 wget 3.00 www.usenix.org 06:11:25 29404 curl 72.00 foo 06:11:28 29475 curl 1.00 foo [...]
11. runqlat
Mostrar a latência da fila de execução (agendador) como um histograma, a cada 5 segundos:
# Runqlat -m 5 Rastreamento da latência da fila de execução ... Pressione Ctrl-C para finalizar. Msecs: distribuição de contagem 0 -> 1: 2085 | ******************************************** 2 -> 3: 8 | | 4 -> 7: 20 | | 8 -> 15: 191 | *** | 16 -> 31: 420 | ******** | Msecs: distribuição de contagem 0 -> 1: 1798 | ********************************************** 2 -> 3: 11 | | 4 -> 7: 45 | * | 8 -> 15: 441 | ********* | 16 -> 31: 1030 | ********************** | Msecs: distribuição de contagem 0 -> 1: 1588 | ************************************************ 2 -> 3: 7 | | 4 -> 7: 49 | * | 8 -> 15: 556 | ************** | 16 -> 31: 1206 | ********************************* [...]
12. perfil
Rastros de pilha de amostra em 49 Hertz, entĂŁo imprima pilhas exclusivas com o nĂşmero de ocorrĂŞncias vistas:
# Perfil Amostragem em 49 Hertz de todos os tĂłpicos pelo usuĂĄrio + pilha de nĂşcleo ... Pressione Ctrl-C para finalizar. ^ C [...] Ffffffff811a2eb0 find_get_entry Ffffffff811a338d pagecache_get_page Ffffffff811a51fa generic_file_read_iter Ffffffff81231f30 __vfs_read Ffffffff81233063 vfs_read Ffffffff81234565 SyS_read Ffffffff818739bb entry_SYSCALL_64_fastpath 00007f4757ff9680 read - dd (14283) 29 Ffffffff8141c067 copy_page_to_iter Ffffffff811a54e8 generic_file_read_iter Ffffffff81231f30 __vfs_read Ffffffff81233063 vfs_read Ffffffff81234565 SyS_read Ffffffff818739bb entry_SYSCALL_64_fastpath 00007f407617d680 lido - dd (14288) 32 Ffffffff813af58c common_file_perm Ffffffff813af6f8 apparmor_file_permission Ffffffff8136f89b security_file_permission Ffffffff81232f6e rw_verify_area Ffffffff8123303e vfs_read Ffffffff81234565 SyS_read Ffffffff818739bb entry_SYSCALL_64_fastpath 00007f407617d680 lido - dd (14288) 39 [...]
5.3. Ferramentas
A seção de ferramentas do bcc no github os lista com descriçþes curtas. Essas ferramentas são principalmente para observabilidade e depuração de desempenho.
Existem dois tipos de ferramentas:
- Single purpose: These tools do one thing and do it well (Unix philosophy). They include execsnoop, opensnoop, ext4slower, biolatency, tcpconnect, oomkill, runqlat, etc. They should be easy to learn and use. Most of the previous examples in the General Performance Checklist were single purpose.
- Multi-tools: These are powerful tools that can do many things, provided you know which arguments and options to use. They featured in the one-liners section earlier on this page, and include trace, argdist, funccount, funclatency, and stackcount.
Each tool has three related files. Using biolatency as an example:
1/3. The tool
$ more tools/biolatency.py #!/usr/bin/python # @lint-avoid-python-3-compatibility-imports # # biolatency Summarize block device I/O latency as a histogram. # For Linux, uses BCC, eBPF. # # USAGE: biolatency [-h] [-T] [-Q] [-m] [-D] [interval] [count] # # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # # 20-Sep-2015 Brendan Gregg Created this. [...]
Tools begin with a block comment to describe basics: what the tool does, its synopsis, major change history.
2/3. An examples file
$ more tools/biolatency_example.txt Demonstrations of biolatency, the Linux eBPF/bcc version. biolatency traces block device I/O (disk I/O), and records the distribution of I/O latency (time), printing this as a histogram when Ctrl-C is hit. For example: # ./biolatency Tracing block device I/O... Hit Ctrl-C to end. ^C usecs : count distribution 0 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 0 | | 64 -> 127 : 1 | | 128 -> 255 : 12 |******** | 256 -> 511 : 15 |********** | 512 -> 1023 : 43 |******************************* | 1024 -> 2047 : 52 |**************************************| 2048 -> 4095 : 47 |********************************** | 4096 -> 8191 : 52 |**************************************| 8192 -> 16383 : 36 |************************** | 16384 -> 32767 : 15 |********** | 32768 -> 65535 : 2 |* | 65536 -> 131071 : 2 |* | The latency of the disk I/O is measured from the issue to the device to its completion. A -Q option can be used to include time queued in the kernel. This example output shows a large mode of latency from about 128 microseconds to about 32767 microseconds (33 milliseconds). The bulk of the I/O was between 1 and 8 ms, which is the expected block device latency for rotational storage devices. The highest latency seen while tracing was between 65 and 131 milliseconds: the last row printed, for which there were 2 I/O. [...]
There are detailed examples files in the /tools directory, which include tool output and discussion of what it means.
3/3. A man page
$ nroff -man man/man8/biolatency.8 | more biolatency(8) biolatency(8) NAME biolatency - Summarize block device I/O latency as a histogram. SYNOPSIS biolatency [-h] [-T] [-Q] [-m] [-D] [interval [count]] DESCRIPTION biolatency traces block device I/O (disk I/O), and records the distri- bution of I/O latency (time). This is printed as a histogram either on Ctrl-C, or after a given interval in seconds. The latency of the disk I/O is measured from the issue to the device to its completion. A -Q option can be used to include time queued in the kernel. This tool uses in-kernel eBPF maps for storing timestamps and the his- togram, for efficiency. This works by tracing various kernel blk_*() functions using dynamic tracing, and will need updating to match any changes to these func- tions. Since this uses BPF, only the root user can use this tool. REQUIREMENTS CONFIG_BPF and bcc. OPTIONS -h Print usage message. -T Include timestamps on output. [...]
The man pages are the reference for what the tool does, what options it has, what the output means including column definitions, and any caveats including overhead.
5.4. Programming
Se vocĂŞ quiser escrever seus prĂłprios programas bcc / eBPF, consulte o Tutorial do desenvolvedor do PcB do bcc . Tem mais de 15 liçþes que cobrem todas as funçþes e ressalvas que vocĂŞ provavelmente irĂĄ encontrar. Consulte tambĂŠm o Guia de ReferĂŞncia do bcc , que explica a API para eBPF C e o bcc Python. Eu criei ambos. Meu objetivo era ser prĂĄtico e conciso: mostre exemplos reais e trechos de cĂłdigo, cubra internals e ressalvas, e faça o mais brevemente possĂvel. Se vocĂŞ pressionar a pĂĄgina para baixo uma ou duas vezes, vocĂŞ atingirĂĄ o prĂłximo tĂtulo, jĂĄ que deliberadamente mantive as seçþes baixas e evite uma parede de texto.
Para as pessoas que tĂŞm mais um interesse casual em como o bcc / BPF estĂĄ programado, resumirei as coisas-chave para saber a seguir, e depois explico o cĂłdigo de uma ferramenta em detalhes.
5 coisas a saber
Se quiser mergulhar na codificação sem ler essas referências, aqui estão cinco coisas a serem conhecidas:
- O eBPF C estå restrito : sem loops ou chamadas de função do kernel. Você só pode usar as funçþes bpf_ * (e alguns compilados com compilação).
- Toda a memória deve ser lida na pilha BPF primeiro antes da manipulação atravÊs do bpf_probe_read (), que faz as verificaçþes necessårias. Se você deseja desreferenciar a-> b-> c-> d, então tente fazer isso primeiro, pois o bcc possui um reescritor que pode transformå-lo no bpf_probe_read () s necessårio. Se não funcionar, adicione bpf_probe_reads () s.
- Existem 3 maneiras de produzir dados do kernel para o usuĂĄrio:
- Bpf_trace_printk () . Depuração apenas, isso escreve para trace_pipe e pode colidir com outros programas e traçadores. Ă muito simples, entĂŁo eu usei isso no inĂcio do tutorial, mas vocĂŞ deve usar o seguinte em vez disso:
- BPF_PERF_OUTPUT () . Uma maneira de enviar detalhes por evento para o espaço do usuårio, atravÊs de uma estrutura personalizada que você define. (O programa Python atualmente precisa de uma versão ct da definição da estrutura - isso deve ser automåtico um dia.)
- BPF_HISTOGRAM () ou outros mapas BPF. Os mapas sĂŁo um hash de valores-chave a partir do qual estruturas de dados mais avançadas podem ser criadas. Eles podem ser usados ââpara estatĂsticas de resumo ou histogramas, e ler periodicamente do espaço do usuĂĄrio (eficiente).
- Use pontos de rastreamento estĂĄticos (traceponits / USDT) em vez de rastreamento dinâmico (kprobes / upsrobes) sempre que possĂvel. Muitas vezes nĂŁo ĂŠ possĂvel, mas tente. O rastreamento dinâmico ĂŠ uma API instĂĄvel, entĂŁo seus programas serĂŁo quebrados se o cĂłdigo que estĂĄ instrumentando mudar de uma versĂŁo para outra.
- Verifique os desenvolvimentos do bcc e os novos idiomas . Comparado com outros traçadores (DTrace / SystemTap), o bcc Python ĂŠ muito mais detalhado e laborioso para codificar. Vai melhorar, entĂŁo, se ĂŠ um incĂ´modo hoje, tenha em mente que ele irĂĄ melhorar. TambĂŠm hĂĄ esforços para criar um idioma de nĂvel superior, que provavelmente usarĂĄ o bcc (seja adicionado ao bcc como outro front-end, ou seja dependente das bibliotecas do bcc).
Exemplo de ferramenta: biolatency.py
A seguir estĂŁo todas as linhas da minha ferramenta biolatency.py original , enumeradas e comentadas:
1 #! / Usr / bin / python 2 # @ lint-avoid-python-3-compatibilidade-importaçþes
Linha 1: somos Python. Linha 2: Eu acredito que suprime um aviso de fiapos (estes foram adicionados ao ambiente de construção de outras empresas principais).
3 # 4 # biolatência Resuma a latência de I / O do dispositivo de bloco como um histograma. 5 # Para Linux, usa BCC, eBPF. 6 # 7 # USO: biolatência [-h] [-T] [-Q] [-m] [-D] [intervalo] [contar] 8 # 9 # Direitos autorais (c) 2015 Brendan Gregg. 10 # Licenciado sob a Licença Apache, Versão 2.0 (a "Licença") 11 # 12 # 20-Set-2015 Brendan Gregg Criou isso.
Tenho um certo estilo para os meus comentårios de cabeçalho. A Linha 4 nomeia a ferramenta e descreve uma única frase. A linha 5 adiciona quaisquer ressalvas: apenas para Linux, usa BCC / eBPF. Em seguida, possui uma linha de sinopse, direitos autorais e um histórico de mudanças importantes.
13 14 de __future__ import print_function 15 do BPC de importação do bcc 16 do tempo importar sono, strftime 17 importação argparse
Observe que importamos o BPF, o que usaremos para interagir com eBPF no kernel.
18 19 argumentos 20 exemplos = "" "exemplos: 21 ./biolatency # resume a latĂŞncia de bloqueio I / O como um histograma 22 ./biolatĂŞncia 1 10 # imprimir 1 segundo resumos, 10 vezes 23 ./biolatency -mT 1 # 1s resumos, milissegundos e timestamps 24 ./biolatency -Q # inclui o tempo de espera do SO no tempo de E / S 25 ./biolatĂŞncia -D # mostra cada dispositivo de disco separadamente 26 "" " 27 parser = argparse.ArgumentParser ( 28 descrição = "Resumir a latĂŞncia de I / O do dispositivo de bloco como um histograma", 29 formatter_class = argparse.RawDescriptionHelpFormatter, 30 epilog = exemplos) 31 parser.add_argument ("- T", "--timestamp", action = "store_true", 32 help = "incluir timestamp na saĂda") 33 parser.add_argument ("- Q", "--queued", action = "store_true", 34 help = "incluir tempo de espera do sistema operacional no tempo de E / S") 35 parser.add_argument ("- m", "--milliseconds", action = "store_true", 36 help = "histograma de milissegundo") 37 parser.add_argument ("- D", "--disks", action = "store_true", 38 help = "imprimir um histograma por dispositivo de disco") 39 parser.add_argument ("interval", nargs = "?", Default = 99999999, 40 help = "intervalo de saĂda, em segundos") 41 parser.add_argument ("count", nargs = "?", Default = 99999999, 42 help = "nĂşmero de saĂdas") 43 args = parser.parse_args () 44 countdown = int (args.count) 45 debug = 0 46
As linhas 19 a 44 sĂŁo processamento de argumentos. Estou usando Argparse de Python aqui.
Minha intenção Ê fazer deste uma ferramenta similar a Unix, algo semelhante ao vmstat / iostat, para facilitar a reconhecer e aprender. Daà o estilo de opçþes e argumentos, e tambÊm fazer uma coisa e fazê-lo bem. Nesse caso, mostrando a latência de E / S do disco como um histograma. Eu poderia ter adicionado um modo para despejar detalhes por evento, mas fez isso uma ferramenta separada, biosnoop.py.
VocĂŞ pode estar escrevendo bcc / eBPF por outros motivos, incluindo agentes para outro software de monitoramento, e nĂŁo precisa se preocupar com a interface do usuĂĄrio.
47 # define o programa BPF 48 bpf_text = "" " 49 #include <uapi / linux / ptrace.h >> 50 #include <linux / blkdev.h> 51 52 typedef struct disk_key { Disco de 53 caracteres [DISK_NAME_LEN]; Ranhura 54 u64; 55} disk_key_t; 56 BPF_HASH (inĂcio, pedido de estrutura *); 57 ARMAZENAMENTO 58 59 // bloqueio de tempo I / O 60 int trace_req_start (struct pt_regs * ctx, struct request * req) 61 { 62 u64 ts = bpf_ktime_get_ns (); 63 start.update (& req, & ts); 64 retornam 0; 65} 66 67 // saĂda 68 int trace_req_completion (struct pt_regs * ctx, struct request * req) 69 { 70 u64 * colher de chĂĄ, delta; 71 72 // buscar timestamp e calcular o delta 73 tsp = start.lookup (& req); 74 se (tsp == 0) { 75 retornar 0; // problema perdido 76} 77 delta = bpf_ktime_get_ns () - * tsp; 78 FATOR 79 80 // armazenar como histograma 81 LOJA 82 83 start.delete (& req); 84 retorna 0; 85} 86 "" "
O programa EBPF ĂŠ declarado como um C em linha atribuĂdo Ă variĂĄvel bpf_text.
A linha 56 declara uma matriz de hash "inĂcio", que usa um ponteiro de solicitação de estrutura como a chave. A função trace_req_start () obtĂŠm um carimbo de data / hora usando bpf_ktime_get_ns () e, em seguida, armazena-o neste hash, digitado por * req (eu apenas estou usando esse endereço de ponteiro como UUID). A função trace_req_completion () entĂŁo faz uma pesquisa no hash com o * req, para buscar a hora de inĂcio da solicitação, que ĂŠ entĂŁo usada para calcular o tempo delta na linha 77. A linha 83 exclui o timestamp do hash.
Os protótipos para essas funçþes começam com uma estrutura pt_regs * para registros e, em seguida, como muitos dos argumentos da função sondada que você deseja incluir. Eu incluà o argumento da primeira função em cada pedido de estrutura *.
Este programa tambĂŠm declara o armazenamento para os dados de saĂda e o armazena, mas hĂĄ um problema: a biolatĂŞncia possui uma opção -D para emitir histogramas por disco, em vez de um histograma para tudo, e isso altera o cĂłdigo de armazenamento. EntĂŁo, este programa eBPF contĂŠm o texto STORAGE e STORE (e FACTOR), que sĂŁo apenas strings que vamos pesquisar e substituir com o prĂłximo cĂłdigo, dependendo das opçþes. Prefiro evitar cĂłdigo-que-escreve-cĂłdigo, se possĂvel, uma vez que dificulta a depuração.
87 88 # substituiçþes de código 89 se args.milliseconds: 90 bpf_text = bpf_text.replace ('FATOR', 'delta / = 1000000;') 91 label = "msecs" Mais 92: 93 bpf_text = bpf_text.replace ('FACTOR', 'delta / = 1000;') 94 label = "usecs" 95 se args.disks: 96 bpf_text = bpf_text.replace ('ARMAZENAMENTO', 97 'BPF_HISTOGRAM (dist, disk_key_t);') 98 bpf_text = bpf_text.replace ('STORE', 99 'chave disk_key_t = {.slot = bpf_log2l (delta)}; '+ 100 'bpf_probe_read (& key.disk, sizeof (key.disk),' + 101 'req-> rq_disk-> disk_name); Dist.incremento (chave); ') Mais 102: 103 bpf_text = bpf_text.replace ('ARMAZENAMENTO', 'BPF_HISTOGRAMA (dist);') 104 bpf_text = bpf_text.replace ('STORE', 105 'dist.increment (bpf_log2l (delta));')
O código FACTOR apenas muda as unidades do tempo que estamos gravando, dependendo da opção -m.
A linha 95 verifica se o pedido por disco foi solicitado (-D) e, em caso afirmativo, substitui as cordas STORAGE e STORE com o cĂłdigo para fazer histogramas por disco. Ele usa a estrutura disk_key declarada na linha 52, que ĂŠ o nome do disco e o slot (balde) no histograma power-of-2. A linha 99 leva o tempo delta e converte-o no Ăndice de slot power-of-2 usando a função helper bpf_log2l (). As linhas 100 e 101 obtĂŞm o nome do disco atravĂŠs de bpf_probe_read (), que ĂŠ como todos os dados sĂŁo copiados na pilha da BPF para operação. A Linha 101 inclui muitas dereferĂŞncias: req-> rq_disk, rq_disk-> disk_name: o reescritor do bcc tambĂŠm transformou estas em bpf_probe_read () s.
As linhas 103 a 105 lidam com o caso do histograma único (não por disco). Um histograma Ê declarado chamado "dist" usando a macro BPF_HISTOGRAM. O slot (balde) Ê encontrado usando a função helper bpf_log2l () e, em seguida, incrementado no histograma.
Este exemplo ĂŠ um pouco corajoso, o que ĂŠ bom (realista) e ruim (intimidante). Veja o tutorial que liguei anteriormente para exemplos mais simples.
106 se debug: 107 imprimir (bpf_text)
Como eu tenho cĂłdigo que escreve cĂłdigo, preciso de uma maneira de depurar o resultado final. Se o debug estiver configurado, imprima.
108 109 # load BPF program 110 b = BPF (texto = bpf_text) 111 se args.queued: 112 b.attach_kprobe (evento = "blk_account_io_start", fn_name = "trace_req_start") Mais 113: 114 b.attach_kprobe (evento = "blk_start_request", fn_name = "trace_req_start") 115 b.attach_kprobe (evento = "blk_mq_start_request", fn_name = "trace_req_start") 116 b.attach_kprobe (evento = "blk_account_io_completion", 117 fn_name = "trace_req_completion") 118
A linha 110 carrega o programa eBPF.
Uma vez que este programa foi escrito antes do EBPF possuir suporte para tracepoint, escrevi para usar kprobes (rastreamento dinâmico do kernel). Ele deve ser reescrito para usar pontos de rastreamento, pois eles são uma API eståvel, embora isso tambÊm requer uma versão do kernel posterior (Linux 4.7+).
Biolatency.py tem uma opção -Q para o tempo incluĂdo na fila no kernel. Podemos ver como ĂŠ implementado neste cĂłdigo. Se estiver configurado, a linha 112 atribui a nossa função eBPF trace_req_start () com um kprobe na função de kernel blk_account_io_start (), que rastreia a solicitação quando estĂĄ na fila no kernel. Se nĂŁo for definido, lnes 114 e 115 anexam nossa função eBPF a diferentes funçþes do kernel, que ĂŠ quando o disco I / O ĂŠ emitido (pode ser um desses). Isso sĂł funciona porque o primeiro argumento para qualquer uma dessas funçþes de kernels ĂŠ o mesmo: solicitação de estrutura *. Se seus argumentos fossem diferentes, eu precisaria de funçþes eBPF separadas para cada um para lidar com isso.
119 imprimir ("Detecção de bloqueio do dispositivo I / O ... Pressione Ctrl-C para finalizar.") 120 121 # saĂda 122 saindo = 0 se args.interval else 1 123 dist = b.get_table ("dist")
A linha 123 busca o histograma "dist" que foi declarado e preenchido pelo cĂłdigo STORAGE / STORE.
124 enquanto (1): 125: 126 sleep (int (args.interval)) 127, exceto KeyboardInterrupt: 128 saindo = 1 129 130 imprimir () 131 if args.timestamp: 132 imprimir ("% - 8s \ n"% strftime ("% H:% M:% S"), final = "") 133 134 dist.print_log2_hist (rĂłtulo, "disco") 135 dist.clear () 136 Contagem regressiva 137 - = 1 138 se sair ou contagem regressiva == 0: 139 exit ()
Isso tem lógica para imprimir todos os intervalos, um certo número de vezes (contagem regressiva). Linhas 131 e 132 imprime um carimbo de data / hora se a opção -T foi usada.
A linha 134 imprime o histograma ou histogramas se estiver fazendo por disco. O primeiro argumento ĂŠ a variĂĄvel de rĂłtulo, que contĂŠm "usecs" ou "msecs", e decora a coluna de valores na saĂda. O segundo argumento ĂŠ rĂłtulos da chave secundĂĄria, se dist tiver histogramas por disco. Como print_log2_hist () pode identificar se este ĂŠ um histograma Ăşnico ou tem uma chave secundĂĄria, vou deixar um exercĂcio aventureiro no spelunking de cĂłdigo dos componentes internos do eBPF e bcc.
A linha 135 limpa o histograma, pronto para o prĂłximo intervalo.
Aqui estĂĄ uma amostra de saĂda:
# Biolatência Rastreamento do dispositivo do bloco I / O ... Pressione Ctrl-C para finalizar. ^ C Usecs: distribuição de contagem 0 -> 1: 0 | | 2 -> 3: 0 | | 4 -> 7: 0 | | 8 -> 15: 0 | | 16 -> 31: 0 | | 32 -> 63: 0 | | 64 -> 127: 1 | | 128 -> 255: 12 | ******** | 256 -> 511: 15 | ********** | 512 -> 1023: 43 | ******************************* | 1024 -> 2047: 52 | *************************************** 2048 -> 4095: 47 | ************************************* 4096 -> 8191: 52 | **************************************** 8192 -> 16383: 36 | ******************************* 16384 -> 32767: 15 | ********** | 32768 -> 65535: 2 | * | 65536 -> 131071: 2 | * |
SaĂda por disco:
# Biolatência -D Rastreamento do dispositivo do bloco I / O ... Pressione Ctrl-C para finalizar. ^ C Disk = 'xvdb' Usecs: distribuição de contagem 0 -> 1: 0 | | 2 -> 3: 0 | | 4 -> 7: 0 | | 8 -> 15: 0 | | 16 -> 31: 0 | | 32 -> 63: 0 | | 64 -> 127: 18 | **** | 128 -> 255: 167 | ********************************************** 256 -> 511: 90 | ********************* | Disk = 'xvdc' Usecs: distribuição de contagem 0 -> 1: 0 | | 2 -> 3: 0 | | 4 -> 7: 0 | | 8 -> 15: 0 | | 16 -> 31: 0 | | 32 -> 63: 0 | | 64 -> 127: 22 | **** | 128 -> 255: 179 | ************************************************************************** 256 -> 511: 88 | ******************* | Disco = 'xvda1' Usecs: distribuição de contagem 0 -> 1: 0 | | 2 -> 3: 0 | | 4 -> 7: 0 | | 8 -> 15: 0 | | 16 -> 31: 0 | | 32 -> 63: 0 | | 64 -> 127: 0 | | 128 -> 255: 0 | | 256 -> 511: 167 | ********************************************** 512 -> 1023: 44 | ********** | 1024 -> 2047: 9 | ** | 2048 -> 4095: 4 | | 4096 -> 8191: 34 | ******** | 8192 -> 16383: 44 | ********** | 16384 -> 32767: 33 | ******* | 32768 -> 65535: 1 | | 65536 -> 131071: 1 | |
A partir da saĂda, podemos ver que xvdb e xvdc possuem histogramas de latĂŞncia semelhantes, enquanto que xvda1 ĂŠ bastante diferente e bimodal, com um modo de latĂŞncia maior entre 4 e 32 milissegundos.
6. perf
EBPF tambĂŠm pode ser usado a partir do comando perf de Linux (aka perf_events) no Linux 4.4 e mais recente. Quanto mais novo for o melhor, como o suporte perf / BPF continua melhorando com cada versĂŁo. Eu jĂĄ forneci um exemplo atĂŠ agora na minha pĂĄgina perf : perf eBPF .
7. ReferĂŞncias
- Bcc (Coleção do compilador BPF) (github): ferramentas, tutorial, guia de referência, exemplos, påginas man.
- BPF docs (github): BPF docs.
- Documentação / rede / filter.txt (kernel.org) BPF e eBPF docs na fonte do kernel.
8. Agradecimentos
Muitas pessoas trabalharam em traçadores e contribuĂram de maneiras diferentes ao longo dos anos para chegar onde estamos hoje, incluindo aqueles que trabalharam nas estruturas Linux que o bcc / eBPF usa: pontos de rastreamento, kprobes, arranha-cĂŠus, ftrace e perf_events. Os contribuidores mais recentes incluem Alexei Starovoitov, que liderou o desenvolvimento do eBPF, e Brenden Blanco, que liderou o desenvolvimento do bcc. Muitas das ferramentas de bcc de propĂłsito Ăşnico foram escritas por mim (execsnoop, opensnoop, biolatency, ext4slower, tcpconnect, gethostlatency, etc.) e duas das mais importantes ferramentas mĂşltiplas (trace e argdist) foram escritas por Sasha Goldshtein. Eu escrevi uma lista mais longa de agradecimentos no final desta publicação . Obrigado a todos!
9. Atualizaçþes
Este Ê principalmente o meu próprio trabalho, apenas porque eu tenho meus próprios URLs à disposição para listar. Eu consertarei isso e continuarei adicionando postagens externas.
2015
- Linux eBPF
- Bcc: Taming Linux 4,3 + Superpoderes de rastreamento
- Tcpconnect e tcpaccept para Linux (bcc)
2016
- Linux eBPF Stack Trace Hack (bcc)
- GrĂĄfico de Fluxo Off-CPU eBPF do Linux (bcc)
- Linux Wakeup e Off-Wake Profiling (bcc)
- ProtĂłtipo do grĂĄfico de cadeia Linux (bcc)
- Rolamentos eBPF / bcc do Linux
- Linux BPF / bcc Road Ahead
- Ubuntu Xenial bcc / BPF
- Recursos de segurança de rastreamento do Linux CCC / BPF
- Linux MySQL Query Query Tracing com bcc / BPF
- Rastreamento de latĂŞncia Linux bcc / BPF ext4
Ferramentas de rastreamento BPF aprimoradas do Linux (eBPF)
Esta pågina mostra exemplos de ferramentas de anålise de desempenho usando aprimoramentos para o BPF (Berkeley Packet Filter) que foram adicionados aos kernels da sÊrie Linux 4.x, permitindo que o BPF faça muito mais do que apenas pacotes de filtragem. Esses aprimoramentos permitem que os programas de anålise personalizados sejam executados no rastreamento dinâmico do Linux, no rastreamento eståtico e nos eventos de criação de perfil.O eBPF possui recursos de rastreamento sem fio semelhantes aos de DTrace e SystemTap, e jå usei muitas das minhas ferramentas do DTraceToolkit para o eBPF. à adequado para responder perguntas como:- Todas as operaçþes ext4 demoram mais de 50 ms?
- O que ĂŠ executar a latĂŞncia da fila, como um histograma?
- Quais pacotes e aplicativos estĂŁo com retransmissĂľes TCP? Trace de forma eficiente (sem rastrear envio / recebimento).
- Qual ĂŠ o rastreamento da pilha quando os segmentos bloqueiam (fora da CPU) e quanto tempo eles bloqueiam?
EBPF tambÊm pode ser usado para módulos de segurança e redes definidas por software. Eu não estou cobrindo aqueles aqui (ainda assim, de qualquer maneira). Observe tambÊm: eBPF Ê chamado de apenas "BPF", especialmente em lkml.Conteúdo da pågina:Existem diferentes front-ends para eBPF, com bcc o mais popular. Nesta pågina, descreverei eBPF, bcc e demonstrei algumas das ferramentas de rastreamento que desenvolvi.1. Captura de tela
Começando com uma captura de tela, aqui estå um exemplo de rastreamento e exibição de E / S de bloco (disco) como um mapa de calor de latência:Eu adicionei algumas anotaçþes a essa captura de tela. Se você Ê novo nesta visualização, veja minha pågina em mapas de calor de latência .Isso usa o rastreamento dinâmico do kernel (kprobes) para as funçþes do instrumento para o problema e a conclusão das E / S do dispositivo de bloco. Os programas eBPF personalizados são executados quando estes kprobes são atingidos, que gravam carimbos de data / hora na questão de E / S, recuperam-nas na conclusão, calculam o tempo delta e, em seguida, armazenam isso em um histograma de log 2. O programa do espaço do usuårio lê essa matriz de histograma periodicamente, uma vez por segundo, e desenha o mapa de calor. O resumo Ê feito no contexto do kernel, para eficiência.2. One Liners
One-liners Ăşteis usando as ferramentas bcc (eBPF):Ferramentas de uso Ăşnico
# Trace novos processos: Execsnoop # O arquivo de rastreamento abre com o processo e o nome do arquivo: Opensnoop # Resumir latência de bloqueio de E / S (disco) como uma distribuição de poder de 2 por disco: Biolatência -D # Resumir o tamanho da E / S do bloco como uma distribuição de poder de 2 pelo nome do programa: tamanho da mordida # Trace operaçþes comuns do sistema de arquivos ext4 com menos de 1 milissegundo: Ext4slower 1 # Trace TCP conexþes ativas (connect ()) com endereço IP e portas: Tcpconnect # Trace TCP passive connections (accept ()) com endereço IP e portas: Tcpaccept # Trace conexþes TCP para a porta local 80, com duração da sessão: Tcplife -L 80 # Trace TCP retransmissþes com endereços IP e estado TCP: Tcpretrans # Testes de pilha de amostra a 49 Hertz por 10 segundos, emite formato dobrado (para gråficos de chama): Perfil -fd -F 49 10 # Trace detalhes e latência das pesquisas de DNS do resolvedor: Gethostlatency # Comandos de rastreamento emitidos em todos os shells bash: Linha de base
Multi Tools: Kernel Dynamic Tracing
# Contagem "tcp_send *" função do kernel, saĂda de impressĂŁo a cada segundo: Funccount -i 1 'tcp_send *' # Count "vfs_ *" chama PID 185: Funccount -p 185 'vfs_ *' # Nomes de arquivo de rastreio abertos, usando o rastreamento dinâmico da função do_sys_open do kernel (): Trace 'p :: do_sys_open "% s", arg2' # Igual a antes ("p :: ĂŠ assumido se nĂŁo for especificado): Trace 'do_sys_open "% s", arg2' # Trace o retorno do kernel do_sys_open () funciton e imprima o retval: Trace 'r :: do_sys_open "ret:% d", retval' # Trace do_nanosleep () função do kernel e o segundo argumento (modo), com os rastreios da pilha do kernel: Traçar -K 'do_nanosleep "modo:% d", arg2' # Trace o modo do_nanosleep () fornecendo o protĂłtipo (nĂŁo ĂŠ necessĂĄrio debuginfo): Trace 'do_nanosleep (struct hrtimer_sleeper * t, modo enum hrtimer_mode) "mode:% d", mode' # Trace do_nanosleep () com o endereço da tarefa (pode ser NULL), observando a desreferĂŞncia: Trace 'do_nanosleep (struct hrtimer_sleeper * t, enum hrtimer_mode mode) "tarefa:% x", t> tarefa " # Contagem de frequĂŞncia tcp_sendmsg () tamanho: Argdist -C 'p :: tcp_sendmsg (struct sock * sk, struct msghdr * msg, size_t size): u32: tamanho' # Resumir o tamanho do tcp_sendmsg () como um histograma de poder de 2: Argdist -H 'p :: tcp_sendmsg (struct sock * sk, struct msghdr * msg, tamanho tamanho_t): u32: tamanho' # Rastreios de pilha de contagem de frequĂŞncia que levam Ă função submit_bio () (problema I / O do disco): Stackcount submit_bio # Resumir a latĂŞncia (tempo gasto) pela função vfs_read () para PID 181: Funclatency -p 181 -u vfs_read
Ferramentas mĂşltiplas: rastreamento dinâmico de nĂvel de usuĂĄrio
# Trace a função de biblioteca libc nanosleep () e imprima os detalhes do sono solicitado: Trace 'p: c: nanosleep (struct timespec * req) "% d sec% d nsec", req-> tv_sec, req-> tv_nsec' # Contar a chamada libc write () para PID 181 por descritor de arquivo: Argdist -p 181 -C 'p: c: write (int fd): int: fd' # Resumir a latência (tempo gasto) por libc getaddrinfo (), como um histograma de power-of-2 em microssegundos: Funclatency.py -u 'c: getaddrinfo'
Multi Tools: Kernel Static Tracing
# Conheça os rastreios de pilha que levaram a E / S do bloco emissor, rastreando seu ponto de sinalização do kernel: Stackcount t: bloco: block_rq_insert
Em construção...Ferramentas múltiplas: rastreamento eståticamente definido pelo usuårio (USDT)
# Trace a sonda pthread_create USDT e imprima arg1 como hexadecimal: Trace 'u: pthread: pthread_create "% x", arg1'
Em construção...Estes one-liners demonstram vårios recursos do bcc / eBPF. Você tambÊm pode imprimir isso como uma cheatsheet.3. Apresentação
Uma conversa recente sobre ferramentas de rastreamento eBPF no LCA 2017 ( slideshare , youtube ):Outras apresentaçþes:- Måquina virtual BPF-in-kernel (slides PDF) por Alexei Starovoitov, Linux Collaboration Summit, 2015.
- Desempenho do Linux 4.x: Usando o BPF Superpowers (slides & video) por Brendan Gregg na conferĂŞncia Performance @ Scale do Facebook, 2016.
- EBPF Trace do Kernel para o espaço do usuårio (slides) por Gary Lin para o dia da tecnologia de compartilhamento, 2016
- Meet-cute entre eBPF e Kernel Tracing (slides) de Viller Hsiao, 2016.
- Olhando para o eBPF Abyss (slides) por Sasha Goldshtein para SREcon Europe 2016.
- Ferramentas de rastreamento do Linux 4.x: usando Superpowers BPF, de Brendan Gregg no USENIX LISA 2016 ( slideshare , PDF ). Incluiu my DĂŞ-me 15 minutos e mudarei sua visĂŁo do demo de rastreamento do Linux .
4. eBPF
O BPF se originou como uma tecnologia para otimizar filtros de pacotes. Se você executar o tcpdump com uma expressão (combinando em um host ou porta), ele Ê compilado em um bytecode BPF ótimo, que Ê executado por uma måquina virtual com sandboxs no kernel. O BPF avançado (tambÊm conhecido como eBPF, mas apenas o BPF) ampliou o que esta måquina virtual BPF poderia fazer: permitindo que ele funcionasse em eventos que não sejam pacotes e outras açþes alÊm de filtragem.O eBPF pode ser usado para redes definidas por software, mitigação de DDoS (queda inicial de pacotes), melhorando o desempenho da rede (eXpress Data Path), detecção de intrusão e muito mais. Nesta pågina, estou focando seu uso em ferramentas de observabilidade, onde Ê usado como mostrado no seguinte fluxo de trabalho:Nossa ferramenta de observabilidade possui o código BPF para executar determinadas açþes: medir a latência, resumir como um histograma, pegar traços de pilha, etc. Esse código BPF Ê compilado para o código de byte BPF e depois enviado para o kernel, onde um verificador pode rejeitå-lo se for Considerado inseguro (que inclui não permitir loops ou ramos para trås). Se o bytecode BPF for aceito, ele poderå ser anexado a diferentes fontes de eventos:- Kprobes : rastreamento dinâmico do kernel.
- Enrugamentos : rastreamento dinâmico do nĂvel do usuĂĄrio.
- Pontos de rastreamento : rastreamento estĂĄtico do kernel.
- Perf_events : amostragem cronometrada e PMCs.
O programa BPF tem duas maneiras de passar dados medidos de volta para o espaço do usuĂĄrio: por detalhes do evento ou por um mapa BPF. Os mapas BPF podem implementar arrays, matrizes associativas e histogramas, e sĂŁo adequados para passar estatĂsticas de resumo.4.1. PrĂŠ-requisitos
Um kernel do Linux compilado com CONFIG_BPF_SYSCALL (por exemplo, o Ubuntu faz isso) e pelo menos o kernel 4.4 (por exemplo, Ubuntu Xenial) para que o histograma, a estatĂstica e o rastreamento por evento sejam suportados. O diagrama a seguir mostra outros recursos com a versĂŁo Linux eBPF suportada chegou em verde:5. bcc
A Coleção BPF Compiler estĂĄ em github.com/iovisor/bcc e fornece uma grande coleção de ferramentas de exemplos de rastreamento, bem como interfaces Python e lua para desenvolvĂŞ-las. O diagrama no canto superior direito desta pĂĄgina ilustra estas ferramentas bcc.Os prĂŠ-requisitos sĂŁo iguais ao eBPF acima, e Python. Se vocĂŞ estiver em um kernel antigo (entre 4.1 e 4.8) e a ferramenta bcc que deseja executar nĂŁo funciona, veja as ferramentas / diretĂłrio antigo do bcc, que podem ter uma versĂŁo legada que emprega soluçþes alternativas.O cĂłdigo de rastreamento de exemplo pode ser encontrado no diretĂłrio bcc / examples / tracing e incluĂdo no /docs/tutorial_bcc_python_developer.md. As ferramentas, sob / diretĂłrio de ferramentas, tambĂŠm podem servir como exemplos. Cada ferramenta tambĂŠm tem um exemplo de arquivo .txt em / tools e uma pĂĄgina de manual em / man / man8.5.1. Instalação
Veja as instruçþes de instalação do bcc para começar em distros diferentes do Linux. Aqui estão as instruçþes do Ubuntu recentes, como um exemplo:# Echo "deb [trust = yes] https://repo.iovisor.org/apt/xenial xenial-nightly main" | \ Sudo tee /etc/apt/sources.list.d/iovisor.list # sudo apt-get update # sudo apt-get install bcc-tools
As ferramentas bcc serão instaladas em / usr / share / bcc / tools.5.2. Lista de verificação de desempenho geral
Esta lista de verificação pode ser útil se você não sabe por onde começar. Ele roteia vårias ferramentas bcc para analisar diferentes alvos, que podem desenterrar a atividade que você desconhecia anteriormente. Primeiro incluà isso no tutorial bcc , depois de uma lista de verificação de ferramentas padrão do Linux. Supþe-se que você tenha executado esses conceitos båsicos (dmesg, vmstat, iostat, top, etc.) e agora quer escavar mais fundo.1. execsnoop
Trace novos processos via exec () syscalls e imprima o nome do processo pai e outros detalhes:# Execsnoop PCOMM PID RET ARGS Bash 15887 0 / usr / bin / man ls PrĂŠconv ââ15894 0 / usr / bin / preconv -e UTF-8 Homem 15896 0 / usr / bin / tbl Homem 15897 0 / usr / bin / nroff -mandoc -rLL = 169n -rLT = 169n -Tutf8 Homem 15898 0 / usr / bin / pager -s Nroff 15900 0 / usr / bin / locale charmap Nroff 15901 0 / usr / bin / groff -mtty-char -Tutf8 -mandoc -rLL = 169n -rLT = 169n Groff 15902 0 / usr / bin / troff -mtty-char -mandoc -rLL = 169n -rLT = 169n -Tutf8 Groff 15903 0 / usr / bin / grotty [...]
2. opensnoop
Trace open () syscalls e nome do processo de impressĂŁo e detalhes do nome do caminho:# Opensnoop PID COMM FD ERR PATH 27159 catalina.sh 3 0 /apps/tomcat8/bin/setclasspath.sh 4057 redis-server 5 0 / proc / 4057 / stat 2360 redis-server 5 0 / proc / 2360 / stat 30668 sshd 4 0 / proc / sys / kernel / ngroups_max 30668 sshd 4 0 / etc / group 30668 sshd 4 0 /root/.ssh/authorized_keys 30668 sshd 4 0 /root/.ssh/authorized_keys 30668 sshd -1 2 / var / run / nologin 30668 sshd -1 2 / etc / nologin 30668 sshd 4 0 /etc/login.defs 30668 sshd 4 0 / etc / passwd 30668 sshd 4 0 / etc / shadow 30668 sshd 4 0 / etc / localtime 4510 snmp-pass 4 0 / proc / cpuinfo [...]
3. ext4slower
Trace as operaçþes lentas do ext4 que são mais lentas do que um limite fornecido (o bcc possui versþes deste para btrfs, XFS e ZFS tambÊm):# Ext4slower 1 Rastreando operaçþes ext4 com menos de 1 ms TIME COMM PID T BYTES OFF_KB LAT (ms) FILENAME 06:49:17 bash 3616 R 128 0 7,75 cksum 06:49:17 cksum 3616 R 39552 0 1.34 [ 06:49:17 cksum 3616 R 96 0 5,36 2 a 3-2,7 06:49:17 cksum 3616 R 96 0 14,94 2to3-3.4 06:49:17 cksum 3616 R 10320 0 6.82 411toppm 06:49:17 cksum 3616 R 65536 0 4.01 a2p 06:49:17 cksum 3616 R 55400 0 8.77 ab 06:49:17 cksum 3616 R 36792 0 16.34 aclocal-1.14 06:49:17 cksum 3616 R 15008 0 19,31 acpi_listen 06:49:17 cksum 3616 R 6123 0 17.23 add-apt-repository 06:49:17 cksum 3616 R 6280 0 18.40 addpart 06:49:17 cksum 3616 R 27696 0 2.16 addr2line 06:49:17 cksum 3616 R 58080 0 10,11 ag
4. biolatĂŞncia
Resumir a latência de E / S do dispositivo de bloco como um histograma a cada segundo:# Biolatência -mT 1 Rastreamento do dispositivo do bloco I / O ... Pressione Ctrl-C para finalizar. 21:33:40 Msecs: distribuição de contagem 0 -> 1: 69 | ******************************************** 2 -> 3: 16 | ********* | 4 -> 7: 6 | *** | 8 -> 15: 21 | ************ | 16 -> 31: 16 | ********* | 32 -> 63: 5 | ** | 64 -> 127: 1 | | 21:33:41 Msecs: distribuição de contagem 0 -> 1: 60 | ************************ | 2 -> 3: 100 | *********************************************** 4 -> 7: 41 | **************** | 8 -> 15: 11 | **** | 16 -> 31: 9 | *** | 32 -> 63: 6 | ** | 64 -> 127: 4 | * | 21:33:42 Msecs: distribuição de contagem 0 -> 1: 110 | ********************************************* 2 -> 3: 78 | ******************************** 4 -> 7: 64 | *********************** | 8 -> 15: 8 | ** | 16 -> 31: 12 | **** | 32 -> 63: 15 | ***** | 64 -> 127: 8 | ** | [...]
5. biosnoop
E / S do dispositivo de bloco de rastreamento com detalhes de processo, disco e latĂŞncia:# Biosnoop TEMPO (s) COMM PID DISK T SETOR BYTES LAT (ms) 0.000004001 supervisionar 1950 xvda1 W 13092560 4096 0.74 0.000178002 supervisionar 1950 xvda1 W 13092432 4096 0.61 0.001469001 supervisionar 1956 xvda1 W 13092440 4096 1.24 0.001588002 supervisionar 1956 xvda1 W 13115128 4096 1.09 1.022346001 supervisionar 1950 xvda1 W 13115272 4096 0.98 1.022568002 supervisionar 1950 xvda1 W 13188496 4096 0.93 1.023534000 supervisionar 1956 xvda1 W 13188520 4096 0.79 1.023585003 supervisionar 1956 xvda1 W 13189512 4096 0.60 2.003920000 xfsaild / md0 456 xvdc W 62901512 8192 0.23 2.003931001 xfsaild / md0 456 xvdb W 62901513 512 0.25 2.004034001 xfsaild / md0 456 xvdb W 62901520 8192 0.35 2.004042000 xfsaild / md0 456 xvdb W 63542016 4096 0.36 2.004204001 kworker / 0: 3 26040 xvdb W 41950344 65536 0.34 2.044352002 supervisionar 1950 xvda1 W 13192672 4096 0.65 [...]
6. cachestat
Mostra a proporção e o tamanho do hit / falta de cache da pågina e resuma todos os segundos:# Cachestat HITS MISSES DIRTIES READ_HIT% WRITE_HIT% BUFFERS_MB CACHED_MB 170610 41607 33 80,4% 19,6% 11 288 157693 6149 33 96,2% 3,7% 11 311 174483 20166 26 89,6% 10,4% 12 389 434778 35 40 100,0% 0,0% 12 389 435723 28 36 100,0% 0,0% 12 389 846183 83800 332534 55,2% 4,5% 13 553 96387 21 24 100,0% 0,0% 13 553 120258 29 44 99,9% 0,0% 13 553 255861 24 33 100,0% 0,0% 13 553 191388 22 32 100,0% 0,0% 13 553 [...]
7. tcpconnect
Trace TCP conexĂľes ativas (connect ()):# Tcpconnect PID COMM IP SADDR DADDR DPORT 25333 recordProgra 4 127.0.0.1 127.0.0.1 28527 25338 curl 4 100.66.3.172 52.22.109.254 80 25340 curl 4 100.66.3.172 31.13.73.36 80 25342 curl 4 100.66.3.172 104.20.25.153 80 25344 curl 4 100.66.3.172 50.56.53.173 80 25365 recordProgra 4 127.0.0.1 127.0.0.1 28527 26119 ssh 6 :: 1 :: 1 22 25388 recordProgra 4 127.0.0.1 127.0.0.1 28527 25220 ssh 6 fe80: 8a3: 9dff: fed5: 6b19 fe80 :: 8a3: 9dff: fed5: 6b19 22 [...]
8. tcpaccept
Trace conexĂľes passivas TCP (accept ()):# Tcpaccept PID COMM IP RADDR LADDR LPORT 2287 sshd 4 11.16.213.254 100.66.3.172 22 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 2287 sshd 6 :: 1 :: 1 22 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 2287 sshd 6 fe80 :: 8a3: 9dff: fed5: 6b19 fe80 :: 8a3: 9dff: fed5: 6b19 22 4057 redis-server 4 127.0.0.1 127.0.0.1 28527 [...]
9. tcpretrans
Transtornos TCP retransmissĂveis e TLPs:# Tcpretrans TIME PID IP LADDR: LPORT T> RADDR: ESTADO DE RUA 01:55:05 0 4 10.153.223.157:22 R> 69.53.245.40:34619 ESTABELECIDO 01:55:05 0 4 10.153.223.157:22 R> 69.53.245.40:34619 ESTABELECIDO 01:55:17 0 4 10.153.223.157:22 R> 69.53.245.40:22957 ESTABELECIDO [...]
10. gethostlatency
Mostrar latĂŞncia para getaddrinfo / gethostbyname [2] chamadas de biblioteca, em todo o sistema:# Gethostlatency TIME PID COMM LATms HOST 06:10:24 28011 wget 90.00 www.iovisor.org 06:10:28 28127 wget 0.00 www.iovisor.org 06:10:41 28404 wget 9.00 www.netflix.com 06:10:48 28544 curl 35.00 www.netflix.com.au 06:11:10 29054 curl 31.00 www.plumgrid.com 06:11:16 29195 curl 3.00 www.facebook.com 06:11:24 25313 wget 3.00 www.usenix.org 06:11:25 29404 curl 72.00 foo 06:11:28 29475 curl 1.00 foo [...]
11. runqlat
Mostrar a latência da fila de execução (agendador) como um histograma, a cada 5 segundos:# Runqlat -m 5 Rastreamento da latência da fila de execução ... Pressione Ctrl-C para finalizar. Msecs: distribuição de contagem 0 -> 1: 2085 | ******************************************** 2 -> 3: 8 | | 4 -> 7: 20 | | 8 -> 15: 191 | *** | 16 -> 31: 420 | ******** | Msecs: distribuição de contagem 0 -> 1: 1798 | ********************************************** 2 -> 3: 11 | | 4 -> 7: 45 | * | 8 -> 15: 441 | ********* | 16 -> 31: 1030 | ********************** | Msecs: distribuição de contagem 0 -> 1: 1588 | ************************************************ 2 -> 3: 7 | | 4 -> 7: 49 | * | 8 -> 15: 556 | ************** | 16 -> 31: 1206 | ********************************* [...]
12. perfil
Rastros de pilha de amostra em 49 Hertz, entĂŁo imprima pilhas exclusivas com o nĂşmero de ocorrĂŞncias vistas:# Perfil Amostragem em 49 Hertz de todos os tĂłpicos pelo usuĂĄrio + pilha de nĂşcleo ... Pressione Ctrl-C para finalizar. ^ C [...] Ffffffff811a2eb0 find_get_entry Ffffffff811a338d pagecache_get_page Ffffffff811a51fa generic_file_read_iter Ffffffff81231f30 __vfs_read Ffffffff81233063 vfs_read Ffffffff81234565 SyS_read Ffffffff818739bb entry_SYSCALL_64_fastpath 00007f4757ff9680 read - dd (14283) 29 Ffffffff8141c067 copy_page_to_iter Ffffffff811a54e8 generic_file_read_iter Ffffffff81231f30 __vfs_read Ffffffff81233063 vfs_read Ffffffff81234565 SyS_read Ffffffff818739bb entry_SYSCALL_64_fastpath 00007f407617d680 lido - dd (14288) 32 Ffffffff813af58c common_file_perm Ffffffff813af6f8 apparmor_file_permission Ffffffff8136f89b security_file_permission Ffffffff81232f6e rw_verify_area Ffffffff8123303e vfs_read Ffffffff81234565 SyS_read Ffffffff818739bb entry_SYSCALL_64_fastpath 00007f407617d680 lido - dd (14288) 39 [...]
5.3. Ferramentas
A seção de ferramentas do bcc no github os lista com descriçþes curtas. Essas ferramentas são principalmente para observabilidade e depuração de desempenho.Existem dois tipos de ferramentas:- Single purpose: These tools do one thing and do it well (Unix philosophy). They include execsnoop, opensnoop, ext4slower, biolatency, tcpconnect, oomkill, runqlat, etc. They should be easy to learn and use. Most of the previous examples in the General Performance Checklist were single purpose.
- Multi-tools: These are powerful tools that can do many things, provided you know which arguments and options to use. They featured in the one-liners section earlier on this page, and include trace, argdist, funccount, funclatency, and stackcount.
Each tool has three related files. Using biolatency as an example:1/3. The tool
$ more tools/biolatency.py #!/usr/bin/python # @lint-avoid-python-3-compatibility-imports # # biolatency Summarize block device I/O latency as a histogram. # For Linux, uses BCC, eBPF. # # USAGE: biolatency [-h] [-T] [-Q] [-m] [-D] [interval] [count] # # Copyright (c) 2015 Brendan Gregg. # Licensed under the Apache License, Version 2.0 (the "License") # # 20-Sep-2015 Brendan Gregg Created this. [...]
Tools begin with a block comment to describe basics: what the tool does, its synopsis, major change history.2/3. An examples file
$ more tools/biolatency_example.txt Demonstrations of biolatency, the Linux eBPF/bcc version. biolatency traces block device I/O (disk I/O), and records the distribution of I/O latency (time), printing this as a histogram when Ctrl-C is hit. For example: # ./biolatency Tracing block device I/O... Hit Ctrl-C to end. ^C usecs : count distribution 0 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 0 | | 64 -> 127 : 1 | | 128 -> 255 : 12 |******** | 256 -> 511 : 15 |********** | 512 -> 1023 : 43 |******************************* | 1024 -> 2047 : 52 |**************************************| 2048 -> 4095 : 47 |********************************** | 4096 -> 8191 : 52 |**************************************| 8192 -> 16383 : 36 |************************** | 16384 -> 32767 : 15 |********** | 32768 -> 65535 : 2 |* | 65536 -> 131071 : 2 |* | The latency of the disk I/O is measured from the issue to the device to its completion. A -Q option can be used to include time queued in the kernel. This example output shows a large mode of latency from about 128 microseconds to about 32767 microseconds (33 milliseconds). The bulk of the I/O was between 1 and 8 ms, which is the expected block device latency for rotational storage devices. The highest latency seen while tracing was between 65 and 131 milliseconds: the last row printed, for which there were 2 I/O. [...]
There are detailed examples files in the /tools directory, which include tool output and discussion of what it means.3/3. A man page
$ nroff -man man/man8/biolatency.8 | more biolatency(8) biolatency(8) NAME biolatency - Summarize block device I/O latency as a histogram. SYNOPSIS biolatency [-h] [-T] [-Q] [-m] [-D] [interval [count]] DESCRIPTION biolatency traces block device I/O (disk I/O), and records the distri- bution of I/O latency (time). This is printed as a histogram either on Ctrl-C, or after a given interval in seconds. The latency of the disk I/O is measured from the issue to the device to its completion. A -Q option can be used to include time queued in the kernel. This tool uses in-kernel eBPF maps for storing timestamps and the his- togram, for efficiency. This works by tracing various kernel blk_*() functions using dynamic tracing, and will need updating to match any changes to these func- tions. Since this uses BPF, only the root user can use this tool. REQUIREMENTS CONFIG_BPF and bcc. OPTIONS -h Print usage message. -T Include timestamps on output. [...]
The man pages are the reference for what the tool does, what options it has, what the output means including column definitions, and any caveats including overhead.5.4. Programming
Se vocĂŞ quiser escrever seus prĂłprios programas bcc / eBPF, consulte o Tutorial do desenvolvedor do PcB do bcc . Tem mais de 15 liçþes que cobrem todas as funçþes e ressalvas que vocĂŞ provavelmente irĂĄ encontrar. Consulte tambĂŠm o Guia de ReferĂŞncia do bcc , que explica a API para eBPF C e o bcc Python. Eu criei ambos. Meu objetivo era ser prĂĄtico e conciso: mostre exemplos reais e trechos de cĂłdigo, cubra internals e ressalvas, e faça o mais brevemente possĂvel. Se vocĂŞ pressionar a pĂĄgina para baixo uma ou duas vezes, vocĂŞ atingirĂĄ o prĂłximo tĂtulo, jĂĄ que deliberadamente mantive as seçþes baixas e evite uma parede de texto.Para as pessoas que tĂŞm mais um interesse casual em como o bcc / BPF estĂĄ programado, resumirei as coisas-chave para saber a seguir, e depois explico o cĂłdigo de uma ferramenta em detalhes.5 coisas a saber
Se quiser mergulhar na codificação sem ler essas referências, aqui estão cinco coisas a serem conhecidas:- O eBPF C estå restrito : sem loops ou chamadas de função do kernel. Você só pode usar as funçþes bpf_ * (e alguns compilados com compilação).
- Toda a memória deve ser lida na pilha BPF primeiro antes da manipulação atravÊs do bpf_probe_read (), que faz as verificaçþes necessårias. Se você deseja desreferenciar a-> b-> c-> d, então tente fazer isso primeiro, pois o bcc possui um reescritor que pode transformå-lo no bpf_probe_read () s necessårio. Se não funcionar, adicione bpf_probe_reads () s.
- Existem 3 maneiras de produzir dados do kernel para o usuĂĄrio:
- Bpf_trace_printk () . Depuração apenas, isso escreve para trace_pipe e pode colidir com outros programas e traçadores. Ă muito simples, entĂŁo eu usei isso no inĂcio do tutorial, mas vocĂŞ deve usar o seguinte em vez disso:
- BPF_PERF_OUTPUT () . Uma maneira de enviar detalhes por evento para o espaço do usuårio, atravÊs de uma estrutura personalizada que você define. (O programa Python atualmente precisa de uma versão ct da definição da estrutura - isso deve ser automåtico um dia.)
- BPF_HISTOGRAM () ou outros mapas BPF. Os mapas sĂŁo um hash de valores-chave a partir do qual estruturas de dados mais avançadas podem ser criadas. Eles podem ser usados ââpara estatĂsticas de resumo ou histogramas, e ler periodicamente do espaço do usuĂĄrio (eficiente).
- Use pontos de rastreamento estĂĄticos (traceponits / USDT) em vez de rastreamento dinâmico (kprobes / upsrobes) sempre que possĂvel. Muitas vezes nĂŁo ĂŠ possĂvel, mas tente. O rastreamento dinâmico ĂŠ uma API instĂĄvel, entĂŁo seus programas serĂŁo quebrados se o cĂłdigo que estĂĄ instrumentando mudar de uma versĂŁo para outra.
- Verifique os desenvolvimentos do bcc e os novos idiomas . Comparado com outros traçadores (DTrace / SystemTap), o bcc Python ĂŠ muito mais detalhado e laborioso para codificar. Vai melhorar, entĂŁo, se ĂŠ um incĂ´modo hoje, tenha em mente que ele irĂĄ melhorar. TambĂŠm hĂĄ esforços para criar um idioma de nĂvel superior, que provavelmente usarĂĄ o bcc (seja adicionado ao bcc como outro front-end, ou seja dependente das bibliotecas do bcc).
Exemplo de ferramenta: biolatency.py
A seguir estão todas as linhas da minha ferramenta biolatency.py original , enumeradas e comentadas:1 #! / Usr / bin / python 2 # @ lint-avoid-python-3-compatibilidade-importaçþes
Linha 1: somos Python. Linha 2: Eu acredito que suprime um aviso de fiapos (estes foram adicionados ao ambiente de construção de outras empresas principais).3 # 4 # biolatência Resuma a latência de I / O do dispositivo de bloco como um histograma. 5 # Para Linux, usa BCC, eBPF. 6 # 7 # USO: biolatência [-h] [-T] [-Q] [-m] [-D] [intervalo] [contar] 8 # 9 # Direitos autorais (c) 2015 Brendan Gregg. 10 # Licenciado sob a Licença Apache, Versão 2.0 (a "Licença") 11 # 12 # 20-Set-2015 Brendan Gregg Criou isso.
Tenho um certo estilo para os meus comentårios de cabeçalho. A Linha 4 nomeia a ferramenta e descreve uma única frase. A linha 5 adiciona quaisquer ressalvas: apenas para Linux, usa BCC / eBPF. Em seguida, possui uma linha de sinopse, direitos autorais e um histórico de mudanças importantes.13 14 de __future__ import print_function 15 do BPC de importação do bcc 16 do tempo importar sono, strftime 17 importação argparse
Observe que importamos o BPF, o que usaremos para interagir com eBPF no kernel.18 19 argumentos 20 exemplos = "" "exemplos: 21 ./biolatency # resume a latĂŞncia de bloqueio I / O como um histograma 22 ./biolatĂŞncia 1 10 # imprimir 1 segundo resumos, 10 vezes 23 ./biolatency -mT 1 # 1s resumos, milissegundos e timestamps 24 ./biolatency -Q # inclui o tempo de espera do SO no tempo de E / S 25 ./biolatĂŞncia -D # mostra cada dispositivo de disco separadamente 26 "" " 27 parser = argparse.ArgumentParser ( 28 descrição = "Resumir a latĂŞncia de I / O do dispositivo de bloco como um histograma", 29 formatter_class = argparse.RawDescriptionHelpFormatter, 30 epilog = exemplos) 31 parser.add_argument ("- T", "--timestamp", action = "store_true", 32 help = "incluir timestamp na saĂda") 33 parser.add_argument ("- Q", "--queued", action = "store_true", 34 help = "incluir tempo de espera do sistema operacional no tempo de E / S") 35 parser.add_argument ("- m", "--milliseconds", action = "store_true", 36 help = "histograma de milissegundo") 37 parser.add_argument ("- D", "--disks", action = "store_true", 38 help = "imprimir um histograma por dispositivo de disco") 39 parser.add_argument ("interval", nargs = "?", Default = 99999999, 40 help = "intervalo de saĂda, em segundos") 41 parser.add_argument ("count", nargs = "?", Default = 99999999, 42 help = "nĂşmero de saĂdas") 43 args = parser.parse_args () 44 countdown = int (args.count) 45 debug = 0 46
As linhas 19 a 44 sĂŁo processamento de argumentos. Estou usando Argparse de Python aqui.Minha intenção ĂŠ fazer deste uma ferramenta similar a Unix, algo semelhante ao vmstat / iostat, para facilitar a reconhecer e aprender. DaĂ o estilo de opçþes e argumentos, e tambĂŠm fazer uma coisa e fazĂŞ-lo bem. Nesse caso, mostrando a latĂŞncia de E / S do disco como um histograma. Eu poderia ter adicionado um modo para despejar detalhes por evento, mas fez isso uma ferramenta separada, biosnoop.py.VocĂŞ pode estar escrevendo bcc / eBPF por outros motivos, incluindo agentes para outro software de monitoramento, e nĂŁo precisa se preocupar com a interface do usuĂĄrio.47 # define o programa BPF 48 bpf_text = "" " 49 #include <uapi / linux / ptrace.h >> 50 #include <linux / blkdev.h> 51 52 typedef struct disk_key { Disco de 53 caracteres [DISK_NAME_LEN]; Ranhura 54 u64; 55} disk_key_t; 56 BPF_HASH (inĂcio, pedido de estrutura *); 57 ARMAZENAMENTO 58 59 // bloqueio de tempo I / O 60 int trace_req_start (struct pt_regs * ctx, struct request * req) 61 { 62 u64 ts = bpf_ktime_get_ns (); 63 start.update (& req, & ts); 64 retornam 0; 65} 66 67 // saĂda 68 int trace_req_completion (struct pt_regs * ctx, struct request * req) 69 { 70 u64 * colher de chĂĄ, delta; 71 72 // buscar timestamp e calcular o delta 73 tsp = start.lookup (& req); 74 se (tsp == 0) { 75 retornar 0; // problema perdido 76} 77 delta = bpf_ktime_get_ns () - * tsp; 78 FATOR 79 80 // armazenar como histograma 81 LOJA 82 83 start.delete (& req); 84 retorna 0; 85} 86 "" "
O programa EBPF ĂŠ declarado como um C em linha atribuĂdo Ă variĂĄvel bpf_text.A linha 56 declara uma matriz de hash "inĂcio", que usa um ponteiro de solicitação de estrutura como a chave. A função trace_req_start () obtĂŠm um carimbo de data / hora usando bpf_ktime_get_ns () e, em seguida, armazena-o neste hash, digitado por * req (eu apenas estou usando esse endereço de ponteiro como UUID). A função trace_req_completion () entĂŁo faz uma pesquisa no hash com o * req, para buscar a hora de inĂcio da solicitação, que ĂŠ entĂŁo usada para calcular o tempo delta na linha 77. A linha 83 exclui o timestamp do hash.Os protĂłtipos para essas funçþes começam com uma estrutura pt_regs * para registros e, em seguida, como muitos dos argumentos da função sondada que vocĂŞ deseja incluir. Eu incluĂ o argumento da primeira função em cada pedido de estrutura *.Este programa tambĂŠm declara o armazenamento para os dados de saĂda e o armazena, mas hĂĄ um problema: a biolatĂŞncia possui uma opção -D para emitir histogramas por disco, em vez de um histograma para tudo, e isso altera o cĂłdigo de armazenamento. EntĂŁo, este programa eBPF contĂŠm o texto STORAGE e STORE (e FACTOR), que sĂŁo apenas strings que vamos pesquisar e substituir com o prĂłximo cĂłdigo, dependendo das opçþes. Prefiro evitar cĂłdigo-que-escreve-cĂłdigo, se possĂvel, uma vez que dificulta a depuração.87 88 # substituiçþes de cĂłdigo 89 se args.milliseconds: 90 bpf_text = bpf_text.replace ('FATOR', 'delta / = 1000000;') 91 label = "msecs" Mais 92: 93 bpf_text = bpf_text.replace ('FACTOR', 'delta / = 1000;') 94 label = "usecs" 95 se args.disks: 96 bpf_text = bpf_text.replace ('ARMAZENAMENTO', 97 'BPF_HISTOGRAM (dist, disk_key_t);') 98 bpf_text = bpf_text.replace ('STORE', 99 'chave disk_key_t = {.slot = bpf_log2l (delta)}; '+ 100 'bpf_probe_read (& key.disk, sizeof (key.disk),' + 101 'req-> rq_disk-> disk_name); Dist.incremento (chave); ') Mais 102: 103 bpf_text = bpf_text.replace ('ARMAZENAMENTO', 'BPF_HISTOGRAMA (dist);') 104 bpf_text = bpf_text.replace ('STORE', 105 'dist.increment (bpf_log2l (delta));')
O cĂłdigo FACTOR apenas muda as unidades do tempo que estamos gravando, dependendo da opção -m.A linha 95 verifica se o pedido por disco foi solicitado (-D) e, em caso afirmativo, substitui as cordas STORAGE e STORE com o cĂłdigo para fazer histogramas por disco. Ele usa a estrutura disk_key declarada na linha 52, que ĂŠ o nome do disco e o slot (balde) no histograma power-of-2. A linha 99 leva o tempo delta e converte-o no Ăndice de slot power-of-2 usando a função helper bpf_log2l (). As linhas 100 e 101 obtĂŞm o nome do disco atravĂŠs de bpf_probe_read (), que ĂŠ como todos os dados sĂŁo copiados na pilha da BPF para operação. A Linha 101 inclui muitas dereferĂŞncias: req-> rq_disk, rq_disk-> disk_name: o reescritor do bcc tambĂŠm transformou estas em bpf_probe_read () s.As linhas 103 a 105 lidam com o caso do histograma Ăşnico (nĂŁo por disco). Um histograma ĂŠ declarado chamado "dist" usando a macro BPF_HISTOGRAM. O slot (balde) ĂŠ encontrado usando a função helper bpf_log2l () e, em seguida, incrementado no histograma.Este exemplo ĂŠ um pouco corajoso, o que ĂŠ bom (realista) e ruim (intimidante). Veja o tutorial que liguei anteriormente para exemplos mais simples.106 se debug: 107 imprimir (bpf_text)
Como eu tenho cĂłdigo que escreve cĂłdigo, preciso de uma maneira de depurar o resultado final. Se o debug estiver configurado, imprima.108 109 # load BPF program 110 b = BPF (texto = bpf_text) 111 se args.queued: 112 b.attach_kprobe (evento = "blk_account_io_start", fn_name = "trace_req_start") Mais 113: 114 b.attach_kprobe (evento = "blk_start_request", fn_name = "trace_req_start") 115 b.attach_kprobe (evento = "blk_mq_start_request", fn_name = "trace_req_start") 116 b.attach_kprobe (evento = "blk_account_io_completion", 117 fn_name = "trace_req_completion") 118
A linha 110 carrega o programa eBPF.Uma vez que este programa foi escrito antes do EBPF possuir suporte para tracepoint, escrevi para usar kprobes (rastreamento dinâmico do kernel). Ele deve ser reescrito para usar pontos de rastreamento, pois eles sĂŁo uma API estĂĄvel, embora isso tambĂŠm requer uma versĂŁo do kernel posterior (Linux 4.7+).Biolatency.py tem uma opção -Q para o tempo incluĂdo na fila no kernel. Podemos ver como ĂŠ implementado neste cĂłdigo. Se estiver configurado, a linha 112 atribui a nossa função eBPF trace_req_start () com um kprobe na função de kernel blk_account_io_start (), que rastreia a solicitação quando estĂĄ na fila no kernel. Se nĂŁo for definido, lnes 114 e 115 anexam nossa função eBPF a diferentes funçþes do kernel, que ĂŠ quando o disco I / O ĂŠ emitido (pode ser um desses). Isso sĂł funciona porque o primeiro argumento para qualquer uma dessas funçþes de kernels ĂŠ o mesmo: solicitação de estrutura *. Se seus argumentos fossem diferentes, eu precisaria de funçþes eBPF separadas para cada um para lidar com isso.119 imprimir ("Detecção de bloqueio do dispositivo I / O ... Pressione Ctrl-C para finalizar.") 120 121 # saĂda 122 saindo = 0 se args.interval else 1 123 dist = b.get_table ("dist")
A linha 123 busca o histograma "dist" que foi declarado e preenchido pelo cĂłdigo STORAGE / STORE.124 enquanto (1): 125: 126 sleep (int (args.interval)) 127, exceto KeyboardInterrupt: 128 saindo = 1 129 130 imprimir () 131 if args.timestamp: 132 imprimir ("% - 8s \ n"% strftime ("% H:% M:% S"), final = "") 133 134 dist.print_log2_hist (rĂłtulo, "disco") 135 dist.clear () 136 Contagem regressiva 137 - = 1 138 se sair ou contagem regressiva == 0: 139 exit ()
Isso tem lĂłgica para imprimir todos os intervalos, um certo nĂşmero de vezes (contagem regressiva). Linhas 131 e 132 imprime um carimbo de data / hora se a opção -T foi usada.A linha 134 imprime o histograma ou histogramas se estiver fazendo por disco. O primeiro argumento ĂŠ a variĂĄvel de rĂłtulo, que contĂŠm "usecs" ou "msecs", e decora a coluna de valores na saĂda. O segundo argumento ĂŠ rĂłtulos da chave secundĂĄria, se dist tiver histogramas por disco. Como print_log2_hist () pode identificar se este ĂŠ um histograma Ăşnico ou tem uma chave secundĂĄria, vou deixar um exercĂcio aventureiro no spelunking de cĂłdigo dos componentes internos do eBPF e bcc.A linha 135 limpa o histograma, pronto para o prĂłximo intervalo.Aqui estĂĄ uma amostra de saĂda:# BiolatĂŞncia Rastreamento do dispositivo do bloco I / O ... Pressione Ctrl-C para finalizar. ^ C Usecs: distribuição de contagem 0 -> 1: 0 | | 2 -> 3: 0 | | 4 -> 7: 0 | | 8 -> 15: 0 | | 16 -> 31: 0 | | 32 -> 63: 0 | | 64 -> 127: 1 | | 128 -> 255: 12 | ******** | 256 -> 511: 15 | ********** | 512 -> 1023: 43 | ******************************* | 1024 -> 2047: 52 | *************************************** 2048 -> 4095: 47 | ************************************* 4096 -> 8191: 52 | **************************************** 8192 -> 16383: 36 | ******************************* 16384 -> 32767: 15 | ********** | 32768 -> 65535: 2 | * | 65536 -> 131071: 2 | * |
SaĂda por disco:# BiolatĂŞncia -D Rastreamento do dispositivo do bloco I / O ... Pressione Ctrl-C para finalizar. ^ C Disk = 'xvdb' Usecs: distribuição de contagem 0 -> 1: 0 | | 2 -> 3: 0 | | 4 -> 7: 0 | | 8 -> 15: 0 | | 16 -> 31: 0 | | 32 -> 63: 0 | | 64 -> 127: 18 | **** | 128 -> 255: 167 | ********************************************** 256 -> 511: 90 | ********************* | Disk = 'xvdc' Usecs: distribuição de contagem 0 -> 1: 0 | | 2 -> 3: 0 | | 4 -> 7: 0 | | 8 -> 15: 0 | | 16 -> 31: 0 | | 32 -> 63: 0 | | 64 -> 127: 22 | **** | 128 -> 255: 179 | ************************************************************************** 256 -> 511: 88 | ******************* | Disco = 'xvda1' Usecs: distribuição de contagem 0 -> 1: 0 | | 2 -> 3: 0 | | 4 -> 7: 0 | | 8 -> 15: 0 | | 16 -> 31: 0 | | 32 -> 63: 0 | | 64 -> 127: 0 | | 128 -> 255: 0 | | 256 -> 511: 167 | ********************************************** 512 -> 1023: 44 | ********** | 1024 -> 2047: 9 | ** | 2048 -> 4095: 4 | | 4096 -> 8191: 34 | ******** | 8192 -> 16383: 44 | ********** | 16384 -> 32767: 33 | ******* | 32768 -> 65535: 1 | | 65536 -> 131071: 1 | |
A partir da saĂda, podemos ver que xvdb e xvdc possuem histogramas de latĂŞncia semelhantes, enquanto que xvda1 ĂŠ bastante diferente e bimodal, com um modo de latĂŞncia maior entre 4 e 32 milissegundos.6. perf
EBPF tambĂŠm pode ser usado a partir do comando perf de Linux (aka perf_events) no Linux 4.4 e mais recente. Quanto mais novo for o melhor, como o suporte perf / BPF continua melhorando com cada versĂŁo. Eu jĂĄ forneci um exemplo atĂŠ agora na minha pĂĄgina perf : perf eBPF .7. ReferĂŞncias
- Bcc (Coleção do compilador BPF) (github): ferramentas, tutorial, guia de referência, exemplos, påginas man.
- BPF docs (github): BPF docs.
- Documentação / rede / filter.txt (kernel.org) BPF e eBPF docs na fonte do kernel.
8. Agradecimentos
Muitas pessoas trabalharam em traçadores e contribuĂram de maneiras diferentes ao longo dos anos para chegar onde estamos hoje, incluindo aqueles que trabalharam nas estruturas Linux que o bcc / eBPF usa: pontos de rastreamento, kprobes, arranha-cĂŠus, ftrace e perf_events. Os contribuidores mais recentes incluem Alexei Starovoitov, que liderou o desenvolvimento do eBPF, e Brenden Blanco, que liderou o desenvolvimento do bcc. Muitas das ferramentas de bcc de propĂłsito Ăşnico foram escritas por mim (execsnoop, opensnoop, biolatency, ext4slower, tcpconnect, gethostlatency, etc.) e duas das mais importantes ferramentas mĂşltiplas (trace e argdist) foram escritas por Sasha Goldshtein. Eu escrevi uma lista mais longa de agradecimentos no final desta publicação . Obrigado a todos!9. Atualizaçþes
Este Ê principalmente o meu próprio trabalho, apenas porque eu tenho meus próprios URLs à disposição para listar. Eu consertarei isso e continuarei adicionando postagens externas.2015
- Linux eBPF
- Bcc: Taming Linux 4,3 + Superpoderes de rastreamento
- Tcpconnect e tcpaccept para Linux (bcc)
2016
- Linux eBPF Stack Trace Hack (bcc)
- GrĂĄfico de Fluxo Off-CPU eBPF do Linux (bcc)
- Linux Wakeup e Off-Wake Profiling (bcc)
- ProtĂłtipo do grĂĄfico de cadeia Linux (bcc)
- Rolamentos eBPF / bcc do Linux
- Linux BPF / bcc Road Ahead
- Ubuntu Xenial bcc / BPF
- Recursos de segurança de rastreamento do Linux CCC / BPF
- Linux MySQL Query Query Tracing com bcc / BPF
- Rastreamento de latĂŞncia Linux bcc / BPF ext4
- Linux bcc / BPF Run Queue (Scheduler) latĂŞncia
- Linux bcc / BPF Node.js rastreamento USDT
- Linux bcc tcptop
- Profiler eficiente baseado em BPF do Linux 4.9
- DTrace para Linux 2016
- Ferramentas de rastreamento do Linux 4.x: usando superpoderes do BPF
- Linux bcc / BPF tcplife: TCP Lifespans
2017
- Golang bcc / BPF Function Tracing
- EBPF, parte 1: passado, presente e futuro por Ferris Ellis
- EBPF, parte 2: Syscall e Tipos de Mapa por Ferris Ellis
Criado: 28 de dezembro de 2016 - Linux bcc / BPF Run Queue (Scheduler) latĂŞncia
- Linux bcc / BPF Node.js rastreamento USDT
- Linux bcc tcptop
- Profiler eficiente baseado em BPF do Linux 4.9
- DTrace para Linux 2016
- Ferramentas de rastreamento do Linux 4.x: usando superpoderes do BPF
- Linux bcc / BPF tcplife: TCP Lifespans
2017
- Golang bcc / BPF Function Tracing
- EBPF, parte 1: passado, presente e futuro por Ferris Ellis
- EBPF, parte 2: Syscall e Tipos de Mapa por Ferris Ellis
Criado: 28 de dezembro de 2016
ComentĂĄrios
Postar um comentĂĄrio