Informazioni su systrace

systrace è lo strumento principale per analizzare le prestazioni dei dispositivi Android. Tuttavia, si tratta di un wrapper intorno agli altri strumenti. È il wrapper lato host atrace, l'eseguibile lato dispositivo che controlla lo spazio utente tracciare e configurare ftrace, nonché il meccanismo di tracciamento principale in Linux in un kernel. systrace utilizza atrace per abilitare il tracciamento, quindi legge il buffer ftrace e aggrega tutto in un visualizzatore HTML autonomo. (Mentre i kernel più recenti supportano per Linux Advanced Berkeley Packet Filtro (eBPF), la seguente documentazione riguarda il kernel 3.18 (senza eFPF), che è quello usato sui Pixel/Pixel XL.

systrace è di proprietà dei team di Google Android e Google Chrome ed è open source nell'ambito Progetto catapult. Nella oltre a systrace, Catapult include altre utilità utili. Ad esempio: ftrace ha più funzionalità di quelle che possono essere attivate direttamente da systrace o atrace e contiene alcune funzionalità avanzate fondamentali per il debug delle prestazioni per risolvere problemi di produzione e facilità d'uso. (Queste funzioni richiedono l'accesso root e spesso un nuovo kernel.)

Esegui systrace

Quando esegui il debug del tremolio su Pixel/Pixel XL, inizia con quanto segue :

./systrace.py sched freq idle am wm gfx view sync binder_driver irq workq input -b 96000

Se combinata con gli indicatori di tracciamento aggiuntivi richiesti per GPU e display dell'attività della pipeline, questo ti permette di tracciare dall'input dell'utente al frame visualizzato sullo schermo. Imposta la dimensione del buffer su un valore grande per evitare di perdere (perché senza un buffer di grandi dimensioni alcune CPU non contengono eventi dopo in qualche punto della traccia).

Quando esegui una verifica systrace, tieni presente che ogni evento viene viene attivato da qualcosa sulla CPU.

Poiché systrace è basato su ftrace e ftrace viene eseguito sulla CPU, qualcosa sulla CPU deve scrivere il buffer ftrace che registra le modifiche hardware. Ciò significa che se vuoi sapere perché lo stato di un recinto del display è cambiato, vedere cosa era in esecuzione sulla CPU nel punto esatto della transizione (qualcosa in esecuzione nella CPU ha attivato la modifica nel log). Questo è alla base dell'analisi del rendimento utilizzando systrace.

Esempio: frame di lavoro

Questo esempio descrive un valore systrace per una normale pipeline dell'interfaccia utente. Per continuare Con l'esempio, scarica il file ZIP delle tracce (che include anche altre tracce a cui si fa riferimento in questa sezione), decomprimi il file, e apri il file systrace_tutorial.html nel browser. Attenzione che questo systrace è un file di grandi dimensioni; a meno che non usi systrace nelle tue attività quotidiane al lavoro, probabilmente si tratta di una traccia molto più grande con molte più informazioni di quelle mai visti prima in una singola traccia.

Per un carico di lavoro periodico e coerente, come Touch Latenza, la pipeline UI contiene quanto segue:

  1. EventThread in SurfaceFlinger riattiva il thread dell'interfaccia utente dell'app, segnalando che è ora per eseguire il rendering di un nuovo frame.
  2. L'app esegue il rendering di un frame nel thread dell'interfaccia utente, in RenderThread e hwuiTasks, utilizzando CPU e delle risorse GPU. Questa è la maggior parte della capacità spesa per la UI.
  3. L'app invia il frame sottoposto a rendering a SurfaceFlinger utilizzando un binder, quindi SurfaceFlinger va in sospensione.
  4. Un secondo EventThread in SurfaceFlinger attiva SurfaceFlinger per l'attivazione di composizione e di visualizzazione. Se SurfaceFlinger stabilisce che non è necessario intervenire fatto, si riattiva.
  5. SurfaceFlinger gestisce la composizione utilizzando Hardware Composer (HWC)/Hardware Composer 2 (HWC2) o GL. Composizione HWC/HWC2 è più veloce e ha una potenza inferiore, ma ha delle limitazioni a seconda del sistema su un chip (SoC). In genere questa operazione richiede circa 4-6 ms, ma può sovrapporsi al passaggio 2 perché Android le app hanno sempre un triplo buffer. (Sebbene le app abbiano sempre un triplo buffer, ci sono potrebbe essere un solo frame in attesa in attesa in SurfaceFlinger, che viene quindi visualizzato è identica al doppio buffering).
  6. SurfaceFlinger invia l'output finale a un conducente del fornitore di nuovo a dormire, in attesa della riattivazione EventThread.

Esaminiamo il frame che inizia da 15.409 ms:

Pipeline UI normale con EventThread in esecuzione
Figura 1. Pipeline UI normale, EventThread in esecuzione
di Gemini Advanced.
.

La Figura 1 mostra un normale frame circondato da frame normali, quindi è una buona punto di partenza per comprendere come funziona la pipeline UI. La riga del thread dell'interfaccia utente per Latenza tocco include colori diversi in momenti diversi. Le barre indicano stati diversi per il thread:

  • Grigio. Dormire.
  • Blu. Eseguibile (potrebbe essere eseguito, ma lo scheduler non lo ha fatto) selezionato per l'esecuzione).
  • Verde. È in esecuzione (lo scheduler pensa che in esecuzione).
  • Rosso. Sonno continuo (generalmente dormire sulla serratura) nel kernel). Può essere indicativo del carico di I/O. Estremamente utile per il debug o problemi di prestazioni.
  • Arancione. Sonno senza interruzioni a causa del carico I/O.

Per visualizzare il motivo del sonno senza interruzioni (disponibile nel sched_blocked_reason tracepoint), seleziona il gruppo di continuità rosso porzione di sonno.

Mentre EventThread è in esecuzione, il thread UI per Touch Latenza diventa eseguibili. Per vedere cosa l'ha attivato, fai clic sulla sezione blu.

Thread UI per Latenza touch
Figura 2. Thread UI per Latenza touch
di Gemini Advanced.
.

La figura 2 mostra il thread UI TouchLatenza attivata da tid 6843, che corrisponde a EventThread. Il thread UI si riattiva, esegue il rendering di un frame e accoda per il consumo da parte di SurfaceFlinger.

Il thread UI si riattiva, esegue il rendering di un frame e lo accoda per consentire a SurfaceFlinger di utilizzarlo
Figura 3. Il thread UI si riattiva, esegue il rendering di un frame e lo accoda affinché SurfaceFlinger utilizzi
di Gemini Advanced.
.

Se il tag binder_driver è abilitato in una traccia, puoi selezionare un'opzione binder per visualizzare le informazioni su tutti i processi transazione.

Figura 4. Transazione Binder
di Gemini Advanced.
.

La Figura 4 mostra che, a 15.423,65 ms, Binder:6832_1 in SurfaceFlinger diventa eseguibile a causa di tid 9579, che è RenderThread di TouchLatenza. Puoi anche consulta codeBuffer su entrambi i lati della transazione binder.

Durante la coda Buffer sul lato SurfaceFlinger, il numero i frame da 1 a 2.

I frame in attesa vanno da 1 a 2
Figura 5. I frame in attesa vanno da 1 a 2
di Gemini Advanced.
.

La figura 5 mostra il triplo buffering, in cui sono presenti due frame completati e un terzo dell'app sta per iniziare. Questo perché abbiamo già abbandonato alcuni frame, quindi l'app conserva due frame in attesa anziché uno per cercare di evitare l'interruzione ulteriormente dei frame.

Poco dopo, il thread principale di SurfaceFlinger viene riattivato da un secondo EventThread, può inviare il vecchio frame in sospeso sul display:

Il thread principale di SurfaceFlinger viene attivato da un secondo EventThread
Figura 6. Il thread principale di SurfaceFlinger viene riattivato di un secondo Thread di eventi
di Gemini Advanced.
.

SurfaceFlinger blocca innanzitutto il vecchio buffer in sospeso, determinando il conteggio del buffer in sospeso diminuisce da 2 a 1.

SurfaceFlinger si aggancia innanzitutto al buffer in attesa precedente
Figura 7. SurfaceFlinger si aggancia innanzitutto alla versione precedente buffer
di Gemini Advanced.
.

Dopo aver bloccato il buffer, SurfaceFlinger imposta la composizione e invia il metodo frame finale al display. (Alcune di queste sezioni sono abilitate nell'ambito tracepoint mdss, quindi potrebbe non essere incluso nel SoC.)

SurfaceFlinger imposta la composizione e invia il frame finale
Figura 8. SurfaceFlinger imposta la composizione e invia il frame finale
di Gemini Advanced.
.

Successivamente, mdss_fb0 si riattiva sulla CPU 0. mdss_fb0 è il thread del kernel della pipeline display per l'output di un frame sottoposto a rendering al display. Possiamo vedere mdss_fb0 come riga separata nella traccia (scorri verso il basso fino ).

mdss_fb0 si riattiva sulla CPU 0
Figura 9. mdss_fb0 si riattiva sulla CPU 0

mdss_fb0 si sveglia, corre per un breve momento, entra in un sonno ininterrotto e poi si riattiva.

Esempio: frame non funzionante

Questo esempio descrive una procedura di sistema utilizzata per eseguire il debug del tremolio di Pixel/Pixel XL. A segui l'esempio, scarica il file zip file di tracce (che include altre tracce a cui viene fatto riferimento ), decomprimi il file e apri il file systrace_tutorial.html nel tuo del browser.

Quando apri systrace, vedrai qualcosa di simile a questo:

Latenza touch in esecuzione su Pixel XL con la maggior parte delle opzioni attivata
Figura 10. Latenza touch in esecuzione su Pixel XL (la maggior parte delle opzioni abilitata, inclusi i punti di traccia mdss e kgsl)
di Gemini Advanced.
.

Quando cerchi jank, controlla la riga FrameFailed in SurfaceFlinger. FrameNon è un miglioramento della qualità della vita fornito da HWC2. Durante la visualizzazione systrace per altri dispositivi, la riga Framepers potrebbe non essere presente se il dispositivo non utilizza HWC2. In nel caso in cui l'oggetto FrameNon sia correlato, con SurfaceFlinger che manca uno dei suoi runtime estremamente regolari e un conteggio del buffer in sospeso per l'app invariato (com.prefabulated.touchlatency) in modalità vsync.

Correlazione Framepers con SurfaceFlinger
Figura 11. Correlazione Framepers con SurfaceFlinger
di Gemini Advanced.
.

La figura 11 mostra un frame mancato a 15598.29&nbps;ms. SurfaceFlinger si è svegliato brevemente alle ore l'intervallo vsync e si è ripreso a dormire senza fare nulla, il che significa SurfaceFlinger ha stabilito che non valeva la pena provare a inviare un frame al display di nuovo. Perché?

Per comprendere la suddivisione della pipeline per questo frame, esamina prima la sezione l'esempio di frame di lavoro riportato sopra per vedere come appare una normale pipeline dell'interfaccia utente in systrace. Quando hai finito, torna al frame mancante e torna indietro. Nota che SurfaceFlinger si attiva e va subito a dormire. Quando viene visualizzato il numero di in attesa da Touch Latenza, ci sono due frame (un buon indizio capire cosa sta succedendo).

SurfaceFlinger si attiva e va subito in sospensione
Figura 12. SurfaceFlinger si riattiva e passa immediatamente a sonno
di Gemini Advanced.
.

Il fatto che SurfaceFlinger contiene frame non è un problema dell'app. Inoltre, SurfaceFlinger si sta svegliando all'ora corretta, quindi non è un SurfaceFlinger problema. Se SurfaceFlinger e l'app sembrano normali, probabilmente problema del driver.

Poiché le tracce di mdss e sync sono abilitate, possiamo ottenere informazioni sulle recinzioni (condivise tra il conducente del display e SurfaceFlinger) che controllano quando i frame vengono inviati al display. Queste recinzioni sono elencate alla voce mdss_fb0_retire, che indica quando è visualizzato un frame. Questi recinti sono forniti come che fanno parte della categoria di traccia sync. A quali recinti corrispondono eventi particolari in SurfaceFlinger dipendono dal SOC e dallo stack di driver, collabora con il fornitore del tuo SOC per capire il significato delle categorie di recinzioni nel tuo le tracce audio.

recinzioni_retire_mdss_fb0
Figura 13. Recinti mdss_fb0_retire

La Figura 13 mostra un frame visualizzato per 33 ms, non 16,7 ms come previsto. A metà di questa sezione, il frame dovrebbe essere stato sostituito con uno nuovo. ma non lo era. Visualizza il frame precedente e cerca qualsiasi cosa.

Frame precedente a frame interrotto
Figura 14. Frame precedente a frame interrotto
di Gemini Advanced.
.

La Figura 14 mostra 14,482 ms per frame. Il segmento a due frame rotto è stato di 33,6 ms, che è più o meno come ci aspettiamo per due frame (il rendering viene eseguito a 60 Hz, 16,7 ms per frame, ossia vicino). Ma 14,482 ms non è vicino a 16,7 ms, qualcosa che non va nella tubazione del display.

Indaga esattamente dove finisce quella recinzione per determinare cosa la controlla.

Esamina la fine del recinto
Figura 15. Esamina la fine del recinto
di Gemini Advanced.
.

Una coda di lavoro contiene __vsync_retire_work_handler, ovvero in funzione quando il recinto cambia. Osservando il codice sorgente del kernel, puoi vedere che ma fa parte del driver del display. Sembra che si trovi nel punto critico per la pipeline di visualizzazione, in modo che venga eseguita il più rapidamente possibile. È eseguibile per circa 70 noi (non un lungo ritardo di pianificazione), ma è una coda di lavoro potrebbero non essere programmati in modo accurato.

Controlla il frame precedente per verificare se ciò ha contribuito al risultato. a volte si tremolano possono sommarsi nel tempo e causare una scadenza non rispettata.

Fotogramma precedente
Figura 16. Fotogramma precedente
di Gemini Advanced.
.

La linea eseguibile sul kworker non è visibile perché lo spettatore la ruota bianco quando è selezionato, ma le statistiche raccontano: 2,3 ms di scheduler il ritardo per parte del percorso critico della pipeline di visualizzazione è non valido. Prima di continuare, correggi il ritardo spostando questa parte del visualizzare il percorso critico della pipeline da una coda di lavoro (che viene eseguita come SCHED_OTHER thread CFS) a un SCHED_FIFO dedicato kthread. Questa funzione richiede garanzie di temporizzazione che le code di lavoro non possono (e non sono fornire.

È questo il motivo del jank? È difficile dire con certezza. Al di fuori di casi facili da diagnosticare come il conflitto di blocchi del kernel che causano i thread durante il sonno, le tracce solitamente non specificano il problema. È possibile che questo tremolio sia la causa della caduta del frame? Certamente. La i tempi di fence dovrebbero essere di 16,7 ms, ma non sono affatto simili a quelli nei frame fino al frame caduto. Dato il grado di stretto accoppiamento della pipeline display è che è possibile che il tremolio dei tempi del recinto abbia causato un calo frame.

In questo esempio, la soluzione prevedeva la conversione __vsync_retire_work_handler da una coda di lavoro a un kthread. Ciò ha portato a notevoli miglioramenti del tremolio e a una riduzione del jank prova della palla che rimbalza. Le tracce successive mostrano tempi di recinto che si muovono molto vicini a 16,7 ms.