ftrace è uno strumento di debug per capire cosa sta succedendo all'interno del kernel Linux. Le sezioni seguenti descrivono la funzionalità di base di ftrace, l'utilizzo di ftrace con atrace (che acquisisce gli eventi del kernel) e ftrace dinamico.
Per informazioni dettagliate sulle funzionalità avanzate di ftrace non disponibili da systrace, consulta la documentazione di ftrace all'indirizzo
<kernel
tree>/Documentation/trace/ftrace.txt
.
Acquisisci gli eventi del kernel con atrace
atrace (frameworks/native/cmds/atrace
) utilizza ftrace per acquisire
gli eventi del kernel. A sua volta, systrace.py (o run_systrace.py nelle versioni successive di
Catapult) utilizza adb per eseguire atrace sul dispositivo. atrace esegue le seguenti operazioni:
- Configura il monitoraggio in modalità utente impostando una proprietà
(
debug.atrace.tags.enableflags
). - Attiva la funzionalità ftrace desiderata scrivendo nei nodi sysfs ftrace appropriati. Tuttavia, poiché ftrace supporta più funzionalità, potresti impostare alcuni nodi sysfs autonomamente e poi utilizzare atrace.
Ad eccezione del monitoraggio in fase di avvio, utilizza atrace per impostare la proprietà sul valore appropriato. La proprietà è una maschera di bit e non esiste un buon modo per determinare i valori corretti, a parte esaminare l'intestazione appropriata (che potrebbe cambiare tra le release di Android).
Attiva gli eventi ftrace
I nodi sysfs di ftrace si trovano in /sys/kernel/tracing
e gli eventi trace
sono suddivisi in categorie in /sys/kernel/tracing/events
.
Per attivare gli eventi in base alla categoria, utilizza:
echo 1 > /sys/kernel/tracing/events/irq/enable
Per attivare gli eventi su base evento, utilizza:
echo 1 > /sys/kernel/tracing/events/sched/sched_wakeup/enable
Se sono stati attivati eventi aggiuntivi scrivendo nei nodi sysfs, questi
non verranno reimpostati da atrace. Un pattern comune per la messa in servizio dei dispositivi Qualcomm consiste nell'abilitare i tracepoint kgsl
(GPU) e mdss
(pipeline di visualizzazione) e poi nell'utilizzare atrace o 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
Puoi anche utilizzare ftrace senza atrace o systrace, il che è utile quando vuoi solo tracce del kernel (o se hai avuto il tempo di scrivere manualmente la proprietà di monitoraggio in modalità utente). Per eseguire solo ftrace:
- Imposta la dimensione del buffer su un valore sufficientemente grande per la traccia:
echo 96000 > /sys/kernel/tracing/buffer_size_kb
- Attiva il monitoraggio:
echo 1 > /sys/kernel/tracing/tracing_on
- Esegui il test, quindi disattiva il monitoraggio:
echo 0 > /sys/kernel/tracing/tracing_on
- Esegui il dump della traccia:
cat /sys/kernel/tracing/trace > /data/local/tmp/trace_output
trace_output fornisce la traccia in formato di testo. Per visualizzarlo utilizzando Catapult, scarica il repository Catapult da GitHub ed esegui trace2html:
catapult/tracing/bin/trace2html ~/path/to/trace_file
Per impostazione predefinita, viene scritto trace_file.html
nella stessa directory.
Correlare gli eventi
Spesso è utile esaminare contemporaneamente la visualizzazione di Catapult e il log ftrace. Ad esempio, alcuni eventi ftrace (in particolare quelli specifici del fornitore) non vengono visualizzati da Catapult. Tuttavia, i timestamp di Catapult sono relativi al primo evento della traccia o a un timestamp specifico dumpato da atrace, mentre i timestamp non elaborati di ftrace si basano su una determinata fonte di clock assoluta nel kernel di Linux.
Per trovare un determinato evento ftrace da un evento Catapult:
- Apri il log ftrace non elaborato. Le tracce nelle versioni recenti di systrace sono
compresse per impostazione predefinita:
- Se hai acquisito il file systrace con
--no-compress
, questo si trova nel file HTML nella sezione che inizia con BEGIN TRACE. - In caso contrario, esegui html2trace dal
tree di Catapult (
tracing/bin/html2trace
) per decomprimere la traccia.
- Se hai acquisito il file systrace con
- Trova il timestamp relativo nella visualizzazione di Catapult.
- Trova una riga all'inizio della traccia contenente
tracing_mark_sync
. Dovrebbe avere un aspetto simile a questo:<5134>-5134 (-----) [003] ...1 68.104349: tracing_mark_write: trace_event_clock_sync: parent_ts=68.104286
Se questa riga non esiste (o se hai utilizzato ftrace senza atrace), i tempi saranno relativi al primo evento nel log ftrace.- Aggiungi il timestamp relativo (in millisecondi) al valore in
parent_ts
(in secondi). - Cerca il nuovo timestamp.
- Aggiungi il timestamp relativo (in millisecondi) al valore in
Questi passaggi dovrebbero portarti all'evento (o almeno molto vicino).
Utilizza ftrace dinamico
Quando systrace e ftrace standard non sono sufficienti, è disponibile un ultimo rimedio: ftrace dinamico. Ftrace dinamico prevede la riscrittura del codice del kernel dopo l'avvio e, di conseguenza, non è disponibile nei kernel di produzione per motivi di sicurezza. Tuttavia, ogni singolo bug di prestazioni difficile nel 2015 e nel 2016 è stato causato in ultima analisi dall'utilizzo di ftrace dinamico. È particolarmente utile per il debug delle sospensioni non interrompibili perché puoi ottenere una traccia dello stack nel kernel ogni volta che esegui la funzione che attiva la sospensione non interrompibile. Puoi anche eseguire il debug di sezioni con interruzioni e preempzioni disattivate, il che può essere molto utile per dimostrare i problemi.
Per attivare ftrace dinamico, modifica il file defconfig del kernel:
- Rimuovi CONFIG_STRICT_MEMORY_RWX (se presente). Se utilizzi la versione 3.18 o successiva e arm64, non è presente.
- Aggiungi quanto segue: CONFIG_DYNAMIC_FTRACE=y, CONFIG_FUNCTION_TRACER=y, CONFIG_IRQSOFF_TRACER=y, CONFIG_FUNCTION_PROFILER=y e CONFIG_PREEMPT_TRACER=y
- Ricostruisci e avvia il nuovo kernel.
- Esegui il seguente comando per verificare la presenza di tracer disponibili:
cat /sys/kernel/tracing/available_tracers
- Verifica che il comando restituisca
function
,irqsoff
,preemptoff
epreemptirqsoff
. - Esegui il seguente comando per assicurarti che ftrace dinamico funzioni:
cat /sys/kernel/tracing/available_filter_functions | grep <a function you care about>
Dopo aver completato questi passaggi, hai a disposizione ftrace dinamico, il profiler delle funzioni, il profiler irqsoff e il profiler preemptoff. Consigliamo vivamente di leggere la documentazione di ftrace su questi argomenti prima di utilizzarli, in quanto sono potenti, ma complessi. irqsoff e preemptoff sono utili principalmente per verificare che i driver potrebbero lasciare le interruzioni o la preemption disattivate per troppo tempo.
Il profiler delle funzioni è la soluzione migliore per i problemi di prestazioni e viene spesso utilizzato per scoprire dove viene chiamata una funzione.
Se i dati del profiler delle funzioni non sono sufficientemente specifici, puoi combinare i tracepoint ftrace con il profiler delle funzioni. Gli eventi ftrace possono essere attivati esattamente come di consueto e verranno interlacciati con la traccia.
Questa opzione è ottima se occasionalmente si verifica un lungo sonno non interrompibile in una funzione specifica che vuoi eseguire il debug: imposta il filtro ftrace sulla funzione che ti interessa, attiva i tracepoint e acquisisci una traccia. Puoi analizzare la traccia risultante con
trace2html
, trovare l'evento che ti interessa e recuperare le tracce dello stack nelle vicinanze
nella traccia non elaborata.
Utilizzare lockstat
A volte, ftrace non è sufficiente ed è necessario eseguire il debug di quella che sembra essere una contesa per i lock del kernel. C'è un'altra opzione del kernel che vale la pena provare:
CONFIG_LOCK_STAT
. Si tratta di un'ultima risorsa, in quanto è estremamente difficile farlo funzionare sui dispositivi Android perché aumenta le dimensioni del kernel oltre le capacità della maggior parte dei dispositivi.
Tuttavia, lockstat utilizza l'infrastruttura di blocco del debug, che è utile per molte altre app. Tutti coloro che si occupano dell'inizializzazione del dispositivo devono trovare un modo per attivare l'opzione su ogni dispositivo perché ci sarà un momento in cui penserai: "Se solo potessi attivare LOCK_STAT
, potrei confermare o confutare che si tratta del problema in cinque minuti anziché in cinque giorni".
Se riesci ad avviare un kernel con l'opzione di configurazione, il monitoraggio dei blocchi è simile a ftrace:
- Attiva il monitoraggio:
echo 1 > /proc/sys/kernel/lock_stat
- Esegui il test.
- Per disattivare il monitoraggio:
echo 0 > /proc/sys/kernel/lock_stat
- Esegui il dump della traccia:
cat /proc/lock_stat > /data/local/tmp/lock_stat
Per informazioni su come interpretare l'output risultante, consulta la documentazione di lockstat
su <kernel>/Documentation/locking/lockstat.txt
.
Utilizzare i tracepoint del fornitore
Utilizza prima i tracepoint a monte, ma a volte dovrai utilizzare i tracepoint del fornitore:
{ "gfx", "Graphics", ATRACE_TAG_GRAPHICS, { { OPT, "events/mdss/enable" }, { OPT, "events/sde/enable" }, { OPT, "events/mali_systrace/enable" }, } },
I tracepoint sono estensibili dal servizio HAL e ti consentono di aggiungere categorie/tracepoint specifici del dispositivo. I tracepoint sono integrati con perfetto, atrace/systrace e l'app di monitoraggio del sistema sul dispositivo.
Le API per l'implementazione di tracepoint/categorie sono:
- listCategories() genera (vec<TracingCategory> categories);
- enableCategories(vec<string> categories) genera (Status status);
- disableAllCategories() genera (stato stato);