O ftrace é uma ferramenta de depuração para entender o que está acontecendo no kernel do Linux. As seções a seguir detalham a funcionalidade básica do ftrace, o uso do ftrace com atrace (que captura eventos do kernel) e o ftrace dinâmico.
Para detalhes sobre a funcionalidade avançada do 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 atrace
O atrace (frameworks/native/cmds/atrace
) usa o ftrace para capturar
eventos do kernel. Por sua vez, o systrace.py (ou run_systrace.py em versões mais recentes do
Catapult) usa o adb
para executar o atrace no dispositivo. O atrace faz o seguinte:
- Configura o rastreamento no modo do usuário definindo uma propriedade
(
debug.atrace.tags.enableflags
). - Ativa a funcionalidade ftrace desejada gravando nos nós sysfs ftrace apropriados. No entanto, como o ftrace oferece suporte a mais recursos, você pode definir alguns nós sysfs e usar o atrace.
Com exceção do rastreamento no momento da inicialização, use o atrace para definir a propriedade com o valor apropriado. A propriedade é uma máscara de bits, e não há uma boa maneira de determinar os valores corretos, a não ser consultando o cabeçalho apropriado, que pode mudar entre as versões do Android.
Ativar eventos de ftrace
Os nós do sysfs do ftrace estão em /sys/kernel/tracing
, e os eventos
de rastreamento são divididos em categorias em /sys/kernel/tracing/events
.
Para ativar eventos por categoria, use:
echo 1 > /sys/kernel/tracing/events/irq/enable
Para ativar eventos individualmente, use:
echo 1 > /sys/kernel/tracing/events/sched/sched_wakeup/enable
Se eventos extras foram ativados pela gravação em nós sysfs, eles
não serão redefinidos pelo atrace. Um padrão comum
para inicialização de dispositivos Qualcomm é ativar os pontos de rastreamento kgsl
(GPU) e
mdss
(pipeline de exibição) e 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 o ftrace sem atrace ou systrace, o que é útil quando você quer apenas rastros do kernel (ou se você escreveu a propriedade de rastreamento do modo de usuário manualmente). Para executar apenas o ftrace:
- Defina o tamanho do buffer para um valor grande o suficiente para o rastreamento:
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
- Faça o dump do rastro:
cat /sys/kernel/tracing/trace > /data/local/tmp/trace_output
O trace_output fornece o rastro em formato de texto. Para visualizar usando o Catapult, acesse o repositório Catapult no GitHub e execute o trace2html:
catapult/tracing/bin/trace2html ~/path/to/trace_file
Por padrão, isso grava trace_file.html
no mesmo
diretório.
Correlacionar eventos
Muitas vezes, é útil analisar a visualização do Catapult e o registro ftrace simultaneamente. Por exemplo, alguns eventos ftrace (principalmente os específicos do fornecedor) não são visualizados pelo Catapult. No entanto, os carimbos de data/hora do Catapult são relativos ao primeiro evento no trace ou a um carimbo de data/hora específico dumpado por um atrace, enquanto os carimbos de data/hora brutos do ftrace são baseados em uma fonte de relógio absoluta específica no kernel do Linux.
Para encontrar um determinado evento ftrace em um evento da Catapult:
- Abra o registro bruto do ftrace. Os rastros em versões recentes do systrace são
compactados por padrão:
- Se você capturou o systrace com
--no-compress
, ele está no arquivo HTML na seção que começa com BEGIN TRACE. - Caso contrário, execute o html2trace na
árvore
Catapult (
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.
- Encontre uma linha no início do rastro 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ê usou o ftrace sem o atrace), os tempos serão relativos ao primeiro evento no registro do ftrace.- Adicione o carimbo de data/hora relativo (em milissegundos) ao valor em
parent_ts
(em segundos). - Procure o novo carimbo de data/hora.
- Adicione o carimbo de data/hora relativo (em milissegundos) ao valor em
Essas etapas devem levar você ao evento (ou pelo menos muito perto dele).
Usar ftrace dinâmico
Quando o systrace e o ftrace padrão não são suficientes, há um último recurso disponível: o ftrace dinâmico. O ftrace dinâmico envolve a reescrita do código do kernel após a inicialização. Por isso, ele não está disponível em kernels de produção por motivos de segurança. No entanto, cada bug de desempenho difícil em 2015 e 2016 foi causado pela raiz usando o ftrace dinâmico. Ele é especialmente poderoso para depurar suspensões ininterruptíveis, porque é possível receber um trace de pilha no kernel sempre que você atinge a função que aciona a suspensão ininterruptível. Também é possível depurar seções com interrupções e preempções desativadas, o que pode ser muito útil para provar problemas.
Para ativar o ftrace dinâmico, edite o defconfig do kernel:
- Remova CONFIG_STRICT_MEMORY_RWX (se estiver presente). Se você estiver usando a versão 3.18 ou mais recente e arm64, ela 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 comando a seguir para verificar se há rastreadores disponíveis:
cat /sys/kernel/tracing/available_tracers
- Confirme se o comando retorna
function
,irqsoff
,preemptoff
epreemptirqsoff
. - Execute o seguinte para garantir que o ftrace dinâmico esteja funcionando:
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 criador de perfil irqsoff e o criador de perfil preemptoff disponíveis. Recomendamos veemente a leitura da documentação do ftrace sobre esses tópicos antes de usá-los, porque eles são poderosos, mas complexos. irqsoff e preemptoff são principalmente úteis para confirmar que os drivers podem estar deixando interrupções ou preempções desativadas por muito tempo.
O perfilador de funções é a melhor opção para problemas de desempenho e é frequentemente usado para descobrir onde uma função está sendo chamada.
Se os dados do analisador de função não forem específicos o suficiente, você poderá combinar
os pontos de rastreamento ftrace com o analisador de função. Os eventos ftrace podem ser ativados da
mesma forma de sempre e serão intercalados com o rastreamento.
Isso é ótimo se houver um tempo de inatividade longo e ininterruptível em uma função específica
que você quer depurar: defina o filtro ftrace para a função que você quer,
ative os pontos de rastreamento e faça um rastreamento. Você pode analisar o rastro resultante com
trace2html
, encontrar o evento que você quer e, em seguida, receber rastros de pilha próximos
no rastro bruto.
Usar o lockstat
Às vezes, o ftrace não é suficiente, e você realmente precisa depurar o que parece
ser uma disputa de bloqueio do kernel. Há mais uma opção de kernel que vale a pena tentar:
CONFIG_LOCK_STAT
. Esse é um último recurso, já que é extremamente
difícil de fazer funcionar em dispositivos Android porque infla o tamanho do
kernel além do que a maioria dos dispositivos pode processar.
No entanto, o lockstat usa a infraestrutura de
bloqueio de depuração, que é útil para muitos outros apps. Todos
que trabalham na ativação do dispositivo precisam encontrar uma maneira de fazer essa opção funcionar
em todos os dispositivos, porque vai haver um momento em que você vai pensar
"Se eu pudesse ativar LOCK_STAT
, poderia confirmar ou refutar isso
como o problema em cinco minutos em vez de cinco dias".
Se você puder inicializar um kernel com a opção de configuração, o rastreamento de bloqueio será semelhante ao ftrace:
- Ative o rastreamento:
echo 1 > /proc/sys/kernel/lock_stat
- Execute o teste.
- Desative o rastreamento:
echo 0 > /proc/sys/kernel/lock_stat
- Faça o dump do seu rastro:
cat /proc/lock_stat > /data/local/tmp/lock_stat
Para receber ajuda para interpretar a saída resultante, consulte a documentação do lockstat
em <kernel>/Documentation/locking/lockstat.txt
.
Usar pontos de rastreamento do fornecedor
Use os pontos de rastreamento upstream primeiro, mas às vezes você precisará usar os pontos de rastreamento 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ível pelo serviço HAL, permitindo que você adicione pontos/categorias de rastreamento específicos do dispositivo. Os pontos de trace estão integrados ao perfetto, ao atrace/systrace e ao app de rastreamento do sistema no dispositivo.
As APIs para implementar pontos de rastreamento/categorias são:
- listCategories() gera (vec<TracingCategory> categories);
- enableCategories(vec<string> categories) gera (Status status);
- disableAllCategories() gera (Status status);