Esercizio 3 - Comprendere il percorso critico e l'analisi dell'attesa
Gli scenari e le attività possono essere ritardati in modo imprevisto. Ad esempio, l'apertura di una scheda all'interno di Microsoft Edge potrebbe richiedere più tempo del previsto.
Un'attività viene definita come una serie di operazioni, alcune sequenziali e alcune parallele, che passano da un evento iniziale a un evento finale. Qualsiasi coppia di eventi iniziale/finale in una traccia può essere vista come un'attività. Il percorso più lungo attraverso questa serie di operazioni è noto come percorso critico. La riduzione della durata di qualsiasi operazione sul percorso critico riduce direttamente la durata dell'attività complessiva.
È consigliabile identificare il processo e il thread che ha completato l'attività e lavorare indietro dal momento in cui l'attività è stata completata. Iniziare analizzando il thread che ha completato l'attività per determinare come il thread ha trascorso la maggior parte del tempo e in quale stato: esecuzione, pronto o attesa.
Tempi di esecuzione significativi indicano che l'utilizzo diretto della CPU potrebbe contribuire alla durata del percorso critico. Il tempo trascorso nello stato pronto indica che altri thread contribuiscono alla durata del percorso critico impedendo l'esecuzione di un thread nel percorso critico. Tempo trascorso in attesa di punti di I/O, timer o altri thread e processi nel percorso critico per il quale il thread corrente era in attesa .
Ogni thread che legge il thread corrente è probabilmente un altro collegamento nel percorso critico e può essere analizzato anche fino alla durata del percorso critico.
Tutte le informazioni necessarie vengono registrate nel grafico Utilizzo CPU (Preciso) e nella tabella in WPA. Gli eventi di utilizzo della CPU registrati dal dispatcher sono associati ai commutatori di contesto. Questa tabella è incentrata su NewThread , ovvero il thread che è stato spostato e ogni riga rappresenta un commutatore di contesto. I dati vengono raccolti per la sequenza di eventi seguente:
NewThread viene disattivato a causa di una chiamata di funzione di blocco.
NewThread è pronto per l'esecuzione dal thread di preparazione.
NewThread viene spostato, quindi si disattiva un vecchio thread.
NewThread viene nuovamente disattivato.
Ecco le colonne interessanti nella tabella Utilizzo CPU (Precise).
Colonna | Dettagli |
---|---|
% Utilizzo CPU | Utilizzo della CPU del nuovo thread dopo la commutazione. Questo valore viene espresso come percentuale del tempo totale della CPU nel periodo di tempo attualmente visibile. |
Numero | Numero di commutatori di contesto rappresentati dalla riga. Si tratta sempre di 1 per singole righe. |
Utilizzo cpu (ms) | Utilizzo della CPU del nuovo thread dopo il commutatore di contesto. |
NewProcess | Processo del nuovo thread. |
NewThreadId | ID thread del nuovo thread. |
NewThreadStack | Stack del nuovo thread quando viene spostato. In genere indica il thread bloccato o in attesa. |
Pronti(s) | Tempo trascorso dal thread nella coda Pronto (a causa di pre-svuotamento o starva della CPU). |
ReadyingThreadId | ID thread del thread pronto. |
ReadyingProcess | Processo proprietario del thread di preparazione. |
ReadyThreadStack | Stack del thread di preparazione. |
ReadyTime (s) | Ora in cui il nuovo thread è stato letto. |
SwitchInTime(s) | Ora in cui il nuovo thread è stato spostato. |
Attese (s) | Tempo di attesa di un thread in una risorsa logica o fisica. L'attesa termina quando NewThreadId viene segnalato da ReadyingThreadId. |
Passaggio 1: Acquisire e aprire una traccia per un problema di ritardo dell'interfaccia utente
Questo esercizio si concentra su un processo fittizio con un'interfaccia utente non rispondente. Il processo è una semplice applicazione Windows Form con un pulsante e una casella di testo. Quando si fa clic sul pulsante, l'interfaccia utente diventa non risponde per 20 secondi finché non viene aggiornata la casella di testo. Si analizzerà il percorso critico di questa operazione.
Scaricare UIDelay.exe da qui.
Avviare UIDelay.exe.
Aprire WPR dal menu Start .
Modificare la configurazione della traccia.
Selezionare Triage di primo livello e utilizzo della CPU.
Selezionare Generale come scenario di prestazioni.
Selezionare Verbose come livello di dettaglio.
Fare clic su Start.
In UIDelay.exefare clic sul pulsante Clic .
- Attendere fino a quando la casella di testo mostra "Fatto!"
In WPR salvare la traccia e aprirla con WPA.
Aprire il menu Traccia e selezionare Configura il percorso dei simboli.
- Specificare il percorso della cache dei simboli. Per altre informazioni sui simboli, vedere la pagina Supporto simboli in MSDN.
Aprire il menu Traccia e selezionare Carica simboli.
Passaggio 2: Identificare il thread dell'interfaccia utente ritardato
Prima di eseguire l'analisi del percorso critico, è prima necessario identificare gli eventi di avvio e arresto dell'attività.
Trovare il grafico Ritardi dell'interfaccia utente nel nodo Attività di sistema di Graph Explorer.
Trascinare e rilasciare il grafico Ritardi dell'interfaccia utente nella scheda analisi.
Trovare il processo diUIDelay.exe .
La durata dovrebbe essere di circa 20 secondi. Ciò indica che si è verificato un ritardo di 20 secondi nel thread dell'interfaccia utente di UIDelay.exe.
L'identificatore del thread dell'interfaccia utente viene visualizzato nella colonna Id thread . In questo esempio, è 24174. Questo valore sarà diverso nella traccia acquisita nel computer. Assicurarsi di prendere nota dell'ID del thread.
Selezionare l'intero intervallo di tempoUIDelay.exe , fare clic con il pulsante destro del mouse e ingrandire.
È consigliabile ingrandire sempre le aree che si sta tentando di analizzare. Riduce la quantità di rumore introdotta da attività non correlate.
Passaggio 3: Analizzare il percorso critico del ritardo dell'interfaccia utente
Ora che si dispone di un punto iniziale di analisi con l'ID thread e i timestamp, è possibile iniziare a esaminare il percorso critico dell'attività per comprendere la sequenza di eventi che portano a un ritardo di 20 secondi nel thread dell'interfaccia utente.
NewThreadId per questo passaggio è il thread identificato nel passaggio 2 (Thread 24174 nel processo di UIDelay.exe).
Aggiungere il grafico Utilizzo CPU (Preciso) alla scheda analisi e applicare l'utilizzo per processo, il set di impostazioni Thread.
Fare clic con il pulsante destro del mouse sulle intestazioni di colonna e rendere visibili le colonne NewThreadStack, ReadyThreadStack e Utilizzo CPU (ms).
Rimuovere le colonne Ready (us) [Max] e Waits (us) [Max]. Il riquadro di visualizzazione dovrebbe ora essere simile al seguente.
Trovare ed espandere il processo diUIDelay.exe nella colonna NewProcess e ordinare per Waits (us) [Sum] facendo clic sull'intestazione della colonna.
Cercare NewThreadId nel processo diUIDelay.exe e analizzare il tempo trascorso nello stato Running, Ready o Waiting.
Nell'esempio seguente è possibile trovare quanto segue:
Il thread richiede 10,025 secondi di tempo della CPU.
Il thread è in attesa di 5,159 secondi.
Il thread si trova nello stato pronto per un periodo di tempo trascurabile (10ms).
Nota È possibile analizzare i 10 secondi di attività della CPU usando la stessa metodologia descritta in Esercizio 2, Passaggio 4 usando il grafico Utilizzo CPU (campione) e esaminando il processo di UIDelay.exe .
Per individuare l'aspetto di NewThreadId, espandere il gruppo NewThreadId per visualizzare NewThreadStack.
Espandere [Radice] e identificare le chiamate di funzione che comportano attese.
In questo esempio ,UIDelay.exe ID thread 24174 è in attesa delle chiamate di funzione di blocco sottostante per 5.073 secondi quando viene attivata la funzione di clic del pulsante:
5.021 secondi sono dovuti a operazioni sotto la funzione ExecuteWMICall .
35 ms sono dovuti a operazioni sotto la funzione PingServer .
Passaggio 3.1: Esaminare il percorso del codice ExecuteWMICall
Se si espande ulteriormente lo stack di chiamate in ExecuteWMICall, si scoprirà che il thread dell'interfaccia utente sta effettivamente dormendo per 5 secondi chiamando in modo esplicito Thread.Sleep.
Questo tipo di comportamento deve essere evitato a tutti i costi perché influisce direttamente sulla velocità di risposta. Se il codice deve attendere le informazioni, deve farlo in modo asincrono in un thread separato e usare un metodo basato su eventi.
Passaggio 3.2: Esaminare il codice PingServer
Se si espande ulteriormente lo stack di chiamate in PingServer, si scoprirà che il thread dell'interfaccia utente ha dipendenze di I/O perché invia comandi Ping sulla rete.
Mentre il ritardo è molto piccolo (35 ms), deve essere evitato in un thread dell'interfaccia utente. Tenere presente che la persona media noterà qualsiasi ritardo dell'interfaccia utente superiore a 100 ms. Questa operazione potrebbe aumentare il tempo totale trascorso oltre 100 ms, causando agli utenti una percezione errata della velocità di risposta.
Tali operazioni devono verificarsi in modo asincrono in un thread separato e non bloccare l'interfaccia utente.