Valorizziamo la tua privacy. Usiamo i cookie per migliorare la tua esperienza sul nostro sito. Utilizzando questo sito accetti la nostra Informativa sulla privacy.

Come Profilare le App WebXR/WebGL

Come Profilare le App WebXR/WebGL

Questo articolo copre i metodi per fare il profiling delle app WebXR e WebGL (indipendentemente dal framework utilizzato). Il profiling è il primo passo per ottimizzare la tua applicazione. Ottimizzare senza fare Profiling è uno spreco di risorse, come descritto in Colli di Bottiglia.

Nota che questo post non affronta come risolvere eventuali problemi di performance trovati. Ci sono molti post e discorsi specifici per ogni collo di bottiglia, ma una volta conosciuto il problema, troverai le risorse necessarie.

Le metriche che profileremo sono tempo della CPU, tempo della GPU, memoria heap di JavaScript, e tempo di caricamento dell’applicazione. L’obiettivo è offrirti la raccolta più completa di informazioni sul profiling gratuitamente. E no: il “conteggio dei poligoni” non è una metrica di cui ci preoccupiamo!

Contenuti 

Colli di Bottiglia 

Senza individuare il collo di bottiglia della tua app, i tuoi sforzi di ottimizzazione non saranno efficaci.

Esempio 

Immagina di stare renderizzando una scena grande con molti oggetti. La tua app sta appena raggiungendo i 60 fps. Puoi ottimizzare il conteggio dei vertici di ciascun oggetto e continuare a restare a 60 fps.

La CPU è responsabile di inviare al GPU il comando per renderizzare ogni oggetto (“Draw Call”). In questo caso, è molto più probabile che la CPU sia sovraccarica di lavoro per inviare le draw calls, mentre la GPU è in attesa di ricevere più lavoro dalla CPU!

Ma non lo sappiamo… finché non misuriamo. Ecco a cosa serve il Profiling.

Tipi di Collo di Bottiglia 

Qualsiasi parte di un’applicazione può causare un collo di bottiglia. Ecco alcuni esempi di colli di bottiglia comuni in ordine di frequenza:

Draw Calls CPU: Troppe chiamate al driver causano troppo overhead.

Garbage: L’applicazione funziona bene, ma produce garbage che causa intoppi a intervalli regolari o irregolari.

Logica CPU: La tua applicazione non riesce a produrre lavoro per la GPU abbastanza velocemente. Spesso causato da simulazioni fisiche pesanti o calcoli di raggio.

Shading Framgmenti GPU: Il costo della prestazione per frammento è troppo alto.

Elaborazione Vertici GPU: Il requisito di elaborazione per vertice è troppo alto.

Risolvere GPU: Causato da post-processing sui GPU mobili.

Recupero Vertici GPU: La memoria per i vertici non viene letta abbastanza velocemente.

Ognuno di essi potrebbe avere sotto-colli di bottiglia.

Metriche 

Le metriche che profileremo sono:

Tempo CPU 

Il lavoro per qualsiasi applicazione XR è diviso tra CPU e GPU. La CPU è responsabile di preparare il lavoro grafico per la GPU per il rendering ed eseguire la logica dell’applicazione.

Qualsiasi codice JavaScript verrà eseguito sulla CPU per preparare draw calls, eseguire il caricamento delle risorse, simulare fisiche, rendere suoni e calcolare le trasformazioni del grafo della scena.

Tempo GPU 

La GPU è responsabile del carico pesante grafico. Mentre la CPU invierà una draw call sul tipo “disegna mesh X con shader Y con texture Z e parametri materiali W”, la GPU eseguirà la rasterizzazione effettiva e le trasformazioni per-vertice per produrre i pixel sullo schermo.

La GPU è anche responsabile di inviare l’immagine finale allo schermo, aspettando “V-Sync” che sincronizza il tasso di aggiornamento dello schermo con quello dell’applicazione.

Frame Rate e V-Sync 

Non usiamo il frame rate (fotogrammi al secondo = fps) per fare il profiling della nostra applicazione.

Questa metrica è solo menzionata per spiegare la complessità di capire come la performance interagisce con il V-Sync. È troppo generica per formulare giudizi utili.

Considera il V-Sync come scadenze fisse: 60, 72, 90 o più scadenze al secondo (il frame rate). Faremo riferimento a “fare il V-Sync” come avere renderizzato ed inviato il fotogramma in tempo per raggiungere la scadenza.

Quando perdi la scadenza, tutto il tuo lavoro viene scartato e devi cercare di recuperare per raggiungere la scadenza successiva. In ambienti a frame rate flessibile, questo può significare che i tuoi driver ti degradano a metà del frame rate.

Se la tua applicazione è appena troppo lenta, questo significa che vedresti ad esempio 30 fps invece di 59 fps, raccontando una storia completamente diversa. Forse la tua applicazione sta performando abbastanza bene con 3ms di tempo CPU e 3ms di tempo GPU, ma poiché il lavoro inizia tardi, perdi il V-Sync per il tuo frame rate target—che dimezza il tuo frame rate effettivo. Nessun conteggio dei vertici, draw call o qualsiasi ottimizzazione classica ti aiuterà qui.

Latenza 

La latenza, il tempo tra input (es. movimento della testa) e il fotogramma completato, è particolarmente importante per la VR. Le implementazioni WebXR generalmente se ne occupano per noi e potrebbero programmare i callback dei fotogrammi un po’ più tardi, se non usiamo il nostro budget dei fotogrammi, per ridurre la latenza. Abbiamo un controllo limitato su questo da WebXR e pertanto non lo copriremo in questo post sul blog.

Garbage Collection 

JavaScript include la gestione della memoria che ti permette di trattare le allocazioni senza preoccupazioni e senza pensieri. Pertanto è comune farlo.

Senza il bisogno di gestire la memoria, perdi il controllo per specificare quando desideri che la tua memoria venga gestita. Questo processo è chiamato “Garbage Collection” e si presenterà a momenti casuali nel ciclo di vita della tua applicazione—ad esempio quando avresti fatto il V-Sync e stavi per inviare il tuo fotogramma.

La garbage collection potrebbe richiedere 0.1 - 10 ms. Considerando che il solito budget di fotogrammi per la VR è 11 ms, assolutamente non vuoi che accada in momenti casuali del tempo.

Quindi come lo evitiamo? L’unico modo è evitare qualsiasi garbage che necessiterebbe di una pulizia. Meno ne produci, più piccoli e rari saranno gli intoppi della garbage collection.

Tempo di Caricamento dell’Applicazione 

Proprio come con il caricamento dei siti web, l’impegno dell’utente a utilizzare la tua app diminuisce con ogni secondo speso in attesa che si carichi. Poiché le applicazioni WebXR sono abbastanza grandi, potrebbe esserci un po’ più di volontà qui rispetto a un sito web, ma non è necessario.

Avviando l’applicazione in anticipo e caricando le risorse che non sono immediatamente necessarie in un secondo momento, possiamo ridurre il tempo di caricamento percepito.

Ottimizzando le risorse e assicurandoci che le impostazioni del nostro server siano ottimali, possiamo ridurre il tempo di caricamento in generale.

E usando formati che richiedono meno parsing, possiamo ridurre la quantità di lavoro che la CPU deve fare dopo aver scaricato le risorse.

Strumenti 

In questo post, copriremo i seguenti strumenti:

Chrome Profiler 

Il profiler integrato di Chrome ti consentirà di profilare il tempo della CPU JavaScript, la Garbage Collection, e in modo molto approssimativo il tempo del frame della GPU.

Puoi trovare la scheda Performance navigando su qualsiasi sito web e premendo Ctrl + Shift + C (Command + Shift + C su MacOS). Trova “Performance” lì. Per registrare una sessione di profiling, premi il pulsante di registrazione in alto a sinistra (Ctrl/Command + E). 3-5 secondi sono di solito pienamente sufficienti dato che solitamente siamo interessati a singoli frame.

Questo funziona anche quando si esegue Remote Debugging su Dispositivi Android come Meta Quest o il tuo smartphone.

Safari ha un profilatore simile per Mac, dispositivi iOS, e il Apple Vision PRO (ad esempio con Safari in esecuzione nel simulatore Apple Vision PRO).

Banner Profilazione WebXR.

Chrome Memory Profiler 

In Garbage Collection descriviamo intoppi in applicazioni che altrimenti girano liscie.

Per trovare quel collo di bottiglia, i Browser forniscono un modo per campionare l’Heap JavaScript. Ecco come abilitarlo in Chrome dal Chrome Profiler descritto sopra:

Come Profilare le App WebXR/WebGL

Esempio 

Quello che segue è un profilo su Meta Quest 2 da Elysian, che si basa su Three.js:

Come Profilare le App WebXR/WebGL

Puoi vedere che il “JS Heap” fluttua tra 14.1 MB - 23.3 MB.

Dovever la memoria scende improvvisamente, troviamo che si verifica Garbage Collection. In questo caso, il GC è così grande che ritarda l’inizio del frame successivo, causando un fotogramma perso:

Come Profilare le App WebXR/WebGL

Di conseguenza, dobbiamo sperare che il fotogramma perso venga riproiettato dall’ultimo fotogramma, altrimenti, si verificherà uno stuttering significativo. Poiché le animazioni non possono essere riproiettate, ci sarà comunque un po’ di stuttering.

Scheda Rete 

Qualsiasi scheda di rete del browser è uno strumento eccellente per fare il profiling del tuo Tempo di Caricamento dell’Applicazione.

Puoi trovare la scheda Rete navigando su qualsiasi sito web e premendo Ctrl + Shift + C (Command + Shift + C su MacOS). Trova “Rete” lì. Per registrare l’attività di rete, ricarica la pagina mentre hai aperta la scheda.

Download Bloccanti 

Se una risorsa non è necessaria immediatamente all’avvio dell’applicazione, dovrebbe essere caricata più tardi, poiché i browser eseguiranno solo richieste parallele limitate alla volta (es. 6 per Chrome).

Come Profilare le App WebXR/WebGL

Meta Quest Performance HUD 

Quando fai il profiling del rendering VR su Meta Quest, puoi usare il Performance HUD.

Si installa più facilmente tramite il Meta Quest Developer Hub.

Questo è particolarmente utile per il debug dei problemi di performance dipendenti dalla vista, poiché puoi usare il visore ricevendo allo stesso tempo un feedback continuo sulle performance.

Esempio 

Nell’esempio qui sotto, Ayushman Johri mostra l’eccellente performance del suo “Vintage Study Room” basato sul Wonderland Engine usando il Meta Quest Performance HUD:

OVR GPU Profiler 

Se incontri colli di bottiglia nel vertex o fragment shading, apprezzerai una comprensione più chiara di cosa richieda più tempo nei tuoi shader.

L’ovrgpuprofiler è uno strumento molto affilato. Se hai una certa comprensione della memoria e dell’architettura della GPU, ti fornisce molte informazioni.

Si esegue installandolo sul tuo visore Meta Quest tramite adb e avviandolo tramite adb shell:

 1    47 metriche supportate:
 2    1       Cicli al Secondo
 3    2       GPU % Bus Occupata
 4    3       % Stallo Fetch Vertici
 5    4       % Stallo Fetch Texture
 6    5       Cache Mancata L1 Texture per Pixel
 7    6       % Miss Texture L1
 8    7       % Miss Texture L2
 9    8       % Ingresso in Memoria di Sistema
10    9       Pre-clipped Poligoni/Secondo
11    10      % Primi Rifiutati Trivialmente
12    11      % Primi Tagliati

(Fonte: developer.oculus.com)

L’output di esempio apparirà come segue:

 1$ adb shell ovrgpuprofiler -r"4,5,6"
 2
 3% Stallo Fetch Texture                    :           2.449
 4Cache Mancata L1 Texture Per Pixel        :           0.124
 5% Miss Texture L1                         :          20.338
 6
 7% Stallo Fetch Texture                    :           2.369
 8Cache Mancata L1 Texture Per Pixel        :           0.122
 9% Miss Texture L1                         :          20.130
10
11% Stallo Fetch Texture                    :           2.580
12Cache Mancata L1 Texture Per Pixel        :           0.127
13% Miss Texture L1
14
15...

(Modificato da: developer.oculus.com)

Molto spesso si dice che leggere e scrivere memoria siano solitamente le operazioni più costose in un programma shader. Se questo è vero dipende da quanto siano ottimizzate per la cache le tue operazioni di memoria.

La memoria cache L1 (“Livello 1”) è incredibilmente veloce. Per assicurarti di usarla, assicurati di seguire il principio di località: accedi alla memoria che è vicina alla memoria che hai acceduto in precedenza.

Spector.js 

Spector.js è un’estensione del browser per Chrome e Firefox che consente di catturare le tracce di frame WebGL. Lo strumento può mostrare l’elenco completo dei comandi e riassumere statistiche come conteggi di vertici e draw call.

Installa dal Chrome Extension Store o dalla Libreria Addon di Firefox. Puoi alternativamente emettere lo strumento tramite tag HTML per browser senza supporto per il plugin.

Come Profilare le App WebXR/WebGL

Per prima cosa abilita lo strumento tramite il pulsante addon in alto, quindi registra un frame cliccando il pulsante di registrazione rosso.

Come Profilare le App WebXR/WebGL

Puoi vedere che Wonderland Engine sta disegnando molti oggetti in un totale di 11 draw call qui. Per qualsiasi altro framework, questo numero sarà 10-100x più alto.

Disjoint Timer Query 

L’estensione EXT_disjoint_timer_query è un’estensione WebGL che consente di misurare il tempo GPU di un set di comandi WebGL. È supportata bene solo su Chrome [Agosto 2023] e se il flag “WebGL Debug Extensions” di Chrome è abilitato.

Poiché tutti i comandi vengono eseguiti in modo asincrono sulla GPU, le misurazioni temporali devono essere programmate anche in modo asincrono.

Wonderland Editor Profiler 

Wonderland Editor è dotato di uno strumento di profiling integrato che aiuta a capire dove la performance della tua app WebXR potrebbe soffrire.

Come Profilare le App WebXR/WebGL

Parole Conclusive 

Ogni framework ha le sue particolari caratteristiche di performance. La maggior parte è legata al draw call prima di qualsiasi altra cosa, e poi al fragment bounding—non c’è bisogno di andare low poly se non a 90 fps!

Abbiamo progettato Wonderland Engine da zero per evitare la maggior parte dei colli di bottiglia sopra menzionati— è gratuito fino a 120k USD di fatturato annuo. Contatta qui per Licenze Enterprise e Supporto.

Prova Wonderland Engine ora e inizia a risparmiare tempo ottimizzando.

Come Profilare le App WebXR/WebGL
Last Update: June 13, 2025

Resta aggiornato.