Come misurare le prestazioni della grafica del browser

Ilmari Heikkinen

Benchmarking della grafica del browser in breve: disegna il più possibile mantenendo una frequenza fotogrammi fluida. Quando la frequenza fotogrammi diminuisce, sai quanto puoi disegnare per ogni fotogramma. Fine del post. No? Ok, ti spiego meglio.

È l'ora di un esempio. Ecco un piccolo snippet di codice con una funzione di benchmarking tick. La funzione tick chiama una funzione draw con un carico di trazione crescente fino a quando il disegno richiede costantemente più di 33 ms.

var t, previousTime;
var drawLoad = 1;
var slowCount = 0;
var maxSlow = 10;
// Note, you might need to polyfill performance.now and requestAnimationFrame
t = previousTime = performance.now();
var tick = function() {
    var maximumFrameTime = 1000/30; // 30 FPS
    t = performance.now();
    var elapsed = t - previousTime;
    previousTime = t;
    if (elapsed < maximumFrameTime || slowCount < maxSlow) {
        if (elapsed < maximumFrameTime) {
            drawLoad+=10;
        } else {
            slowCount++;
        }
        draw(drawLoad);
        requestAnimationFrame(tick);
    } else {
        // found maximum sustainable load at 30 FPS
        document.getElementById('res').innerHTML = ("could draw "+(drawLoad)+" in " +
            maximumFrameTime + " ms");
    }
};
requestAnimationFrame(tick);

Vedi l'esempio dal vivo su jsFiddle

Puoi vedere come il benchmark continua a disegnare sempre più fino a quando non rallenta. Si tratta di un modo semplice e pratico per capire quanto puoi disegnare con una frequenza fotogrammi uniforme. Puoi anche aggiungere la tua funzione di disegno all'esempio ed eseguire un benchmarking personalizzato.

Avvertenze ed errori comuni durante il benchmarking degli elementi grafici del browser

Quindi, se l'esempio precedente è il modo giusto per farlo, quali sono i modi meno carini? I modi che ti portano a eseguire un benchmarking di elementi non correlati o che forniscono metriche sul rendimento insolite, che non sembrano avere nulla a che fare con la velocità di esecuzione della tua app. Mi fa piacere che tu abbia chiesto, ecco le due più comuni che ho visto sul Web.

Misurazione dei f/s massimi: disegna un po' ogni fotogramma e misura gli f/s. Non funziona bene per misurare le prestazioni grafiche su Chrome perché l'implementazione della grafica sottostante è sincronizzata con la frequenza di aggiornamento dello schermo (quindi ottieni un massimo di 60 aggiornamenti dello schermo al secondo). Anche la misurazione della velocità delle chiamate di disegno non sarà molto utile, poiché il sistema di disegno di Chrome inserisce i comandi di disegno in un buffer dei comandi che viene eseguito al successivo aggiornamento della schermata.

L'utilizzo di setTimeout per la misurazione delle prestazioni grafiche è un'altra cattiva idea. L'intervallo setTimeout è limitato a 4 ms nei browser, quindi il massimo che puoi ottenere è 250 FPS. Storicamente, i browser avevano intervalli minimi diversi, quindi potresti aver avuto un benchmark di disegno banale molto rotto che ha mostrato il browser A in esecuzione a 250 FPS (intervallo minimo di 4 ms) e il browser B in esecuzione a 100 FPS (intervallo minimo di 10 ms). È evidente che A è più veloce! No, Potrebbe essere che B ha eseguito il codice di disegno più velocemente di A, ad esempio A ha impiegato 3 ms e B ha impiegato 1 ms. Non influisce sugli FPS, poiché il tempo di disegno è inferiore all'intervallo minimo di setTimeout. E se il browser esegue il rendering in modo asincrono, tutte le scommesse sono disattivate. Non utilizzare setTimeout a meno che tu non sappia cosa stai facendo.

Come fare allora

Un modo migliore per stabilire un benchmark consiste nell'utilizzare un carico di disegno realistico e moltiplicarlo finché la frequenza fotogrammi non inizia a deteriorarsi. Ad esempio, se stai scrivendo un gioco dall'alto verso il basso con un terreno a mappa di riquadri, prova a disegnare la mappa dei riquadri ogni frame e controlla se viene eseguita a 60 FPS. Se sì, aumenta il carico (disegna la mappa dei riquadri due volte ogni frame, con una luce intermedia). Continua ad aumentare finché il valore di FPS non scende a un nuovo livello stabile. Ora sai quanti livelli di mappa dei riquadri puoi disegnare per frame.

Ogni applicazione grafica ha esigenze diverse, pertanto dovresti scrivere i tuoi benchmark tenendo presenti queste esigenze. Misura le funzionalità grafiche che utilizzi nella tua app. Se riscontri uno scenario lento, prova a ridurlo fino alla porzione di codice più piccola che lo riproduce (e invia una segnalazione di bug all'indirizzo new.crbug.com se dovrebbe essere più veloce).

Per scoprire come scrivere codice grafico web ad alte prestazioni, dai un'occhiata alla presentazione di Google I/O 2012 di Nat Duca e Tom Wiltzius del team dedicato alle GPU di Chrome.