O ftrace é uma ferramenta de depuração que ajuda a entender o que está acontecendo no Kernel do Linux As seções a seguir detalham a funcionalidade básica do ftrace, o ftrace com atrace (que captura eventos do kernel) e ftrace dinâmico.
Para detalhes sobre a funcionalidade avançada de ftrace que não está disponível no
systrace, consulte a documentação do ftrace em
<kernel
tree>/Documentation/trace/ftrace.txt
Capturar eventos do kernel com o atrace
o atrace (frameworks/native/cmds/atrace
) usa ftrace para capturar
eventos do kernel. Por sua vez, o systrace.py (ou run_systrace.py em versões posteriores do
Catapult) usa o adb.
para executar o atrace no dispositivo. O atrace faz o seguinte:
- Configura o rastreamento do modo de usuário definindo uma propriedade
(
debug.atrace.tags.enableflags
). - Ativa a funcionalidade desejada do ftrace gravando no nós do ftrace. No entanto, como o ftrace é compatível com mais recursos, você pode definir alguns nós do sysfs e, em seguida, use o atrace.
Com exceção do rastreamento do tempo de inicialização, use o atrace para definir o para o valor apropriado. A propriedade é uma bitmask e não há maneira de determinar os valores corretos sem olhar para o cabeçalho apropriado (o que pode mudar entre as versões do Android).
Ativar eventos ftrace
Os nós do ftrace sysfs estão em /sys/kernel/tracing
e trace
os eventos são divididos em categorias no /sys/kernel/tracing/events
.
Para ativar eventos por categoria, use:
echo 1 > /sys/kernel/tracing/events/irq/enable
Para ativar eventos por evento, use:
echo 1 > /sys/kernel/tracing/events/sched/sched_wakeup/enable
Se eventos extras tiverem sido ativados ao gravar nos nós sysfs, eles
não podem ser redefinidos pelo atrace. Um padrão comum
para a exibição do dispositivo Qualcomm é ativar kgsl
(GPU) e
mdss
(pipeline de exibição) e depois usar atrace ou
Systrace:
adb shell "echo 1 > /sys/kernel/tracing/events/mdss/enable"
adb shell "echo 1 > /sys/kernel/tracing/events/kgsl/enable"
./systrace.py sched freq idle am wm gfx view binder_driver irq workq ss sync -t 10 -b 96000 -o full_trace.html
Você também pode usar ftrace sem atrace ou systrace, que são útil quando você quer traces somente do kernel (ou se você se esforçou para escrever a propriedade de rastreamento do modo de usuário manualmente). Para executar apenas ftrace:
- Defina o tamanho do buffer com um valor grande o suficiente para o trace:
echo 96000 > /sys/kernel/tracing/buffer_size_kb
- Ative o rastreamento:
echo 1 > /sys/kernel/tracing/tracing_on
- Execute o teste e desative o rastreamento:
echo 0 > /sys/kernel/tracing/tracing_on
- Despeje o rastro:
cat /sys/kernel/tracing/trace > /data/local/tmp/trace_output
O trace_output fornece o trace em forma de texto. Para visualizá-lo usando Catapult, pegue a Catapult repositório (em inglês) do GitHub e execute trace2html:
catapult/tracing/bin/trace2html ~/path/to/trace_file
Por padrão, isso grava trace_file.html
na mesma
diretório.
Correlacionar eventos
A visualização da Catapult e do ftrace pode ser útil registrar simultaneamente; por exemplo, alguns eventos ftrace (especialmente específicos do fornecedor não são visualizados pela Catapult. No entanto, os carimbos de data/hora da Catapult são em relação ao primeiro evento no trace ou a um carimbo de data/hora específico despejados pelo atrace, enquanto os carimbos de data/hora de ftrace brutos são baseados em um determinado origem absoluta do relógio no kernel do Linux.
Para encontrar um determinado evento ftrace em um evento do Catapult:
- Abra o registro ftrace bruto. Os traces em versões recentes do Systrace são
compactado por padrão:
- Se você capturou o Systrace com
--no-compress
, ele está o arquivo html na seção que começa com BEGIN TRACE. - Caso contrário, execute o html2trace na
Catapult
árvore (
tracing/bin/html2trace
) para descompactar o rastro.
- Se você capturou o Systrace com
- Encontre o carimbo de data/hora relativo na visualização do Catapult.
- Encontrar uma linha no início do trace que contenha
tracing_mark_sync
: O código será semelhante a este:<5134>-5134 (-----) [003] ...1 68.104349: tracing_mark_write: trace_event_clock_sync: parent_ts=68.104286
Se essa linha não existir (ou se você tiver usado ftrace sem atrace), os tempos serão relativos a partir do primeiro evento no registro do ftrace.- Adicione o carimbo de data/hora relativo (em milissegundos) ao valor em
parent_ts
(em segundos). - Pesquise o novo carimbo de data/hora.
- Adicione o carimbo de data/hora relativo (em milissegundos) ao valor em
Essas etapas devem colocar você no evento (ou pelo menos muito próximo dele).
Usar ftrace dinâmico
Quando o Systrace e o ftrace padrão não são suficientes, há uma última recurso disponível: ftrace dinâmico O ftrace dinâmico envolve reescrever do código do kernel após a inicialização e, por isso, não fica disponível na produção os kernels por motivos de segurança. No entanto, todos os bugs de desempenho difíceis A causa raiz de 2015 e 2016 foi o uso de ftrace dinâmico. É especialmente eficiente para depurar períodos de inatividade ininterruptos porque você pode conseguir um stack trace no kernel toda vez que você clica na função que aciona a suspensão ininterrupta. Também é possível depurar seções com interrupções e preempções desativadas, o que pode ser muito úteis para comprovar problemas.
Para ativar o ftrace dinâmico, edite o defconfig do seu kernel:
- Remova CONFIG_STRICT_MEMORY_RWX (se estiver presente). Se você estiver usando a versão 3.18 ou mais recente e arm64, não estará lá.
- Adicione o seguinte: CONFIG_DYNAMIC_FTRACE=y, CONFIG_FUNCTION_TRACER=y, CONFIG_IRQSOFF_TRACER=y, CONFIG_FUNCTION_PROFILER=y e CONFIG_PREEMPT_TRACER=y
- Recrie e inicialize o novo kernel.
- Execute o seguinte comando para verificar os rastreadores disponíveis:
cat /sys/kernel/tracing/available_tracers
- Confirme se o comando retorna
function
,irqsoff
.preemptoff
epreemptirqsoff
. - Execute o seguinte comando para garantir o funcionamento do ftrace dinâmico:
cat /sys/kernel/tracing/available_filter_functions | grep <a function you care about>
Depois de concluir essas etapas, você terá o ftrace dinâmico, o criador de perfil de função, o Profiler irqsoff e o criador de perfil preemptoff estão disponíveis. Nós forçamos recomendamos a leitura da documentação do ftrace sobre esses tópicos antes de usar porque são poderosos, mas complexos. irqsoff e preemptoff são, principalmente, útil para confirmar se os motoristas estão deixando para trás desativada por muito tempo.
O criador de perfil de função é a melhor opção para problemas de desempenho e costuma ser usada para descobrir onde uma função está sendo chamada.
Mostrar problema: foto HDR + visor giratório
Nesse problema, usar um Pixel XL para tirar uma foto HDR+ e imediatamente girava o visor sempre que ficava instável. Usamos o criador de perfil de função para e depurar o problema em menos de uma hora. Para acompanhar o exemplo, fazer o download do arquivo zip dos rastros (que também incluir outros traces mencionados nesta seção), descompacte o arquivo e abra o trace_30898724.html no navegador.
O rastro mostra várias linhas de execução bloqueadas no processo do servidor da câmera
suspensão ininterrupta às ion_client_destroy
. Esse é um sistema
função de íon, mas não deve ser chamado com muita frequência porque é provável que os
abrangem muitas alocações. Inicialmente, a culpa estava no código Hexagon
Halide, que era um dos culpados (criava um novo cliente para cada
alocação de íons e destruíram aquele cliente quando a alocação foi liberada, o que
era muito caro). Migração para um único cliente de íons para todo o Hexágono
alocações melhoraram a situação, mas a instabilidade não foi corrigida.
Agora, precisamos saber quem está ligando para ion_client_destroy
,
então é hora de usar o criador de perfil de função:
- Como as funções às vezes são renomeadas pelo compilador, confirme
ion_client_destroy
está lá usando:cat /sys/kernel/tracing/available_filter_functions | grep ion_client_destroy
- Depois de confirmar que está lá, use-o como o filtro ftrace:
echo ion_client_destroy > /sys/kernel/tracing/set_ftrace_filter
- Ative o criador de perfil de função:
echo function > /sys/kernel/tracing/current_tracer
- Ative os stack traces sempre que uma função de filtro for chamada:
echo func_stack_trace > /sys/kernel/tracing/trace_options
- Aumente o tamanho do buffer:
echo 64000 > /sys/kernel/tracing/buffer_size_kb
- Ative o rastreamento:
echo 1 > /sys/kernel/tracing/trace_on
- Execute o teste e receba o trace:
cat /sys/kernel/tracing/trace > /data/local/tmp/trace
- Abra o rastro para encontrar vários stack traces:
cameraserver-643 [003] ...1 94.192991: ion_client_destroy <-ion_release cameraserver-643 [003] ...1 94.192997: <stack trace> => ftrace_ops_no_ops => ftrace_graph_call => ion_client_destroy => ion_release => __fput => ____fput => task_work_run => do_notify_resume => work_pending
Com base na inspeção do driver de íons, podemos ver que
ion_client_destroy
está recebendo spam pelo fechamento de uma função do espaço do usuário
um fd para /dev/ion
, não um driver de kernel aleatório. Ao pesquisar no
Base de código do Android para \"/dev/ion\"
, encontramos vários drivers de fornecedores
fazer a mesma coisa que o driver Hexagon e abrir/fechar
/dev/ion
(criando e destruindo um novo cliente iônico) toda vez que ele
precisam de uma nova alocação de íons. Alterar para
usar
um único cliente ion durante o ciclo de vida do processo corrigiu o bug.
Se os dados do criador de perfil de função não forem específicos o suficiente, será possível combinar
tracepoints ftrace com o criador de perfil de função. Os eventos ftrace podem ser ativados
exatamente da mesma forma que de costume, e eles serão intercalados com seu rastro.
Isso é ótimo quando há um sono longo e ininterrupto ocasional em um horário específico
que você quer depurar: defina o filtro ftrace para a função desejada
ativar tracepoints, capturar trace. É possível analisar o rastro resultante com
trace2html
, encontre o evento que você quer e acesse stack traces próximos
no rastreamento bruto.
Usar bloqueio estatístico
Às vezes, o ftrace não é suficiente e é preciso depurar o que parece ser
pode ser contenção de bloqueio do kernel. Vale a pena testar mais uma opção de kernel:
CONFIG_LOCK_STAT
: Este é um último recurso, pois é extremamente
difícil de trabalhar em dispositivos Android porque infla o tamanho do
além do kernel que a maioria dos dispositivos consegue suportar.
No entanto, o lockstat usa o valor de
infraestrutura de bloqueio, o que é útil para muitos outros apps. Todos
ao trabalhar na exibição do dispositivo deve descobrir uma maneira de fazer essa opção funcionar.
em todos os dispositivos, porque haverá momento em que você pensará
"Se eu pudesse ativar o LOCK_STAT
, poderia confirmar ou refutar isso
como o problema em cinco minutos em vez de cinco dias".
Mostrar problema: trava em SCHED_FIFO quando os núcleos estão na carga máxima com non-SCHED_FIFO
Nesse problema, a linha de execução SCHED_FIFO parou quando todos os núcleos estavam no máximo carregado com threads não-SCHED_FIFO. Tínhamos rastros mostrando um bloqueio significativo contenção de um fd em aplicativos de RV, mas não conseguimos identificar facilmente o fd em uso. Para acompanhar o exemplo, faça o download do arquivo de traces (que também inclui outros traces mencionados neste ), descompacte o arquivo e abra o arquivo trace_30905547.html no navegador.
Nossa hipótese era que o próprio ftrace fosse a fonte da contenção de bloqueio, quando um de baixa prioridade começaria a gravar no pipe ftrace e depois ou interrompida antes de liberar o bloqueio. Esse é o pior cenário foi exacerbado por um conjunto de linhas de execução de prioridade extremamente baixa gravando no marcador ftrace junto com algumas linhas de execução de prioridade mais alta girando nas CPUs para para simular um dispositivo completamente carregado.
Como não foi possível usar o ftrace para depuração, temos LOCK_STAT
funcionando
e desativou todos os outros rastreamentos do app. Os resultados mostraram que o bloqueio
contenção na verdade foi de ftrace porque nenhuma contenção apareceu em
o trace de bloqueio quando o ftrace não estava em execução.
Se for possível inicializar um kernel com a opção de configuração, o rastreamento de bloqueio será semelhante à ftrace:
- Ative o rastreamento:
echo 1 > /proc/sys/kernel/lock_stat
- Execute o teste.
- Desative o rastreamento:
echo 0 > /proc/sys/kernel/lock_stat
- Despeje seu rastro:
cat /proc/lock_stat > /data/local/tmp/lock_stat
Se precisar de ajuda para interpretar a saída resultante, consulte a documentação da lockstat
em <kernel>/Documentation/locking/lockstat.txt
.
Usar tracepoints do fornecedor
Use os tracepoints upstream primeiro, mas às vezes você vai precisar usar os tracepoints do fornecedor:
{ "gfx", "Graphics", ATRACE_TAG_GRAPHICS, { { OPT, "events/mdss/enable" }, { OPT, "events/sde/enable" }, { OPT, "events/mali_systrace/enable" }, } },
Os pontos de rastreamento são extensíveis pelo serviço HAL, permitindo adicionar rastros específicos do dispositivo pontos/categorias. Os pontos de rastreamento são integrados ao perfetto, atrace/systrace e sistemas no dispositivo app de rastreamento padrão.
As APIs para implementar pontos de rastreamento/categorias são:
- listCategories()generates (vec<TracingCategory>>);
- enableCategories(vec<string>>) gera (status de status);
- desativaAllCategories() gera (status de status);