Mierzenie wydajności grafiki w przeglądarce

Ilmari Heikkinen

Benchmarkowanie grafiki w przeglądarce w pigułce: rysuj jak najwięcej, zachowując płynną liczbę klatek. Gdy liczba klatek na sekundę spadnie, wiesz, ile możesz narysować na każdą klatkę. Koniec posta. Nie? OK, wyjaśnię to dokładniej.

Czas na przykłady. Oto krótki fragment kodu z funkcją porównywania tick. Funkcja tick wywołuje funkcję draw z coraz większym obciążeniem rysowania, aż rysowanie będzie trwało dłużej niż 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);

​Zobacz przykład na żywo w jsFiddle

Możesz zobaczyć, jak punkt odniesienia ciągle się przesuwa, aż dochodzi do punktu, w którym spowalnia. To przyjemny i prosty sposób na określenie, ile możesz narysować przy płynnej liczbie klatek na sekundę. Możesz też podłączyć do przykładu własną funkcję rysowania i przeprowadzić niestandardowe testy porównawcze.

Wskazówki i wpadki podczas testowania porównawczego grafiki w przeglądarce

Jeśli powyższy przykład jest dobrym sposobem, to jakie są nie tak dobre sposoby? Sposoby, które prowadzą do porównywania niemających ze sobą nic wspólnego rzeczy lub które dają dziwne dane o wydajności, które nie mają nic wspólnego z szybkością działania aplikacji. Oto 2 najczęstsze błędy, które widzę w internecie.

Pomiar maksymalnej liczby klatek na sekundę: rysowanie niewielkiego fragmentu każdej klatki i pomiar liczby klatek na sekundę. Nie sprawdza się ona w przypadku pomiaru wydajności grafiki w Chrome, ponieważ implementacja grafiki jest synchronizowana z częstotliwością odświeżania ekranu (co daje maksymalnie 60 aktualizacji ekranu na sekundę). Zliczanie szybkości wywołania funkcji rysowania też nie będzie zbyt przydatne, ponieważ system rysowania w Chrome umieszcza polecenia rysowania w buforze poleceń, który jest wykonywany przy następnym odświeżeniu ekranu.

Używanie setTimeout do pomiaru wydajności grafiki to kolejny zły pomysł. Timeout ma ograniczony interwał 4 ms w przeglądarkach, więc maksymalna wartość, jaką można uzyskać, to 250 FPS. W przeszłości przeglądarki miały różne minimalne przedziały, więc mogłeś mieć bardzo uszkodzony test porównawczy trivial draw, który pokazywał, że przeglądarka A działa z prędkością 250 FPS (minimalny przedział 4 ms), a przeglądarka B – z prędkością 100 FPS (minimalny przedział 10 ms). Wyraźnie widać, że A jest szybsze. Nie! Możliwe, że B wykonało kod rysowania szybciej niż A, np. A zajęło 3 ms, a B – 1 ms. Nie wpływa to na liczbę klatek na sekundę, ponieważ czas rysowania jest krótszy niż minimalny interwał funkcji setTimeout. Jeśli przeglądarka renderuje asynchronicznie, wszystko jest możliwe. Nie używaj funkcji setTimeout, chyba że wiesz, co robisz.

Jak to zrobić

Lepszym sposobem na przetestowanie jest użycie realistycznego obciążenia rysowania i jego pomnożenie, aż częstotliwość wyświetlania klatek zacznie spadać. Jeśli np. tworzysz grę z widokiem z lotu ptaka i używasz mapy kafelkowej, spróbuj ją narysować w każdej klatce i sprawdź, czy działa z prędkością 60 FPS. Jeśli tak, zwiększ obciążenie (rysuj mapę kafelków 2 razy na każdą klatkę, z przerwą między nimi). Kontynuuj zwiększanie, aż liczba klatek na sekundę spadnie do nowego stabilnego poziomu. Wiesz już, ile warstw mapy kafelków możesz narysować na każdy kadr.

Różne aplikacje graficzne mają różne potrzeby, dlatego benchmarki powinny być tworzone z uwzględnieniem tych różnic. Zmierz funkcje graficzne, których używasz w aplikacji. Gdy znajdziesz scenariusz, który działa wolno, spróbuj go zredukować do najmniejszego fragmentu kodu, który go wywołuje (i zgłoś błąd na stronie new.crbug.com, jeśli ma być szybszy).

Aby dowiedzieć się, jak pisać wydajny kod grafiki internetowej, obejrzyj wystąpienie Nata Ducy i Toma Wiltziusa z zespołu odpowiedzialnego za GPU w Chrome podczas konferencji Google I/O 2012.