Как измерить производительность графики браузера

Ilmari Heikkinen

Коротко о тестировании браузерной графики: рисуйте как можно больше, сохраняя при этом плавную частоту кадров. Как только ваша частота кадров упадет, вы поймете, сколько вы можете отрисовать за кадр. Конец поста. Нет? Хорошо, я объясню еще.

Время примера! Вот небольшой фрагмент кода с функцией tick тестирования. Функция tick вызывает функцию draw с увеличивающейся нагрузкой до тех пор, пока прорисовка не будет длиться постоянно дольше 33 мс.

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);

См. живой пример на jsFiddle.

Вы можете видеть, как тест продолжает рисовать все больше и больше, пока не достигнет точки, в которой он замедляется. Это хороший и простой способ выяснить, сколько вы можете нарисовать с плавной частотой кадров. Вы также можете подключить к примеру свою собственную функцию рисования и провести собственный сравнительный анализ, ура!

Распространенные предостережения и ошибки при тестировании графики браузера

Итак, если приведенный выше пример — хороший способ сделать это, то какие есть не очень хорошие способы? Способы, которые приводят к сравнительному анализу несвязанных вещей или дают странные показатели производительности, которые, похоже, не имеют никакого отношения к скорости работы вашего приложения. Рад, что вы спросили, вот два наиболее распространенных из них, которые я видел в Интернете.

Измерение максимального FPS: нарисуйте каждый кадр понемногу и измерьте FPS. Он не подходит для измерения производительности графики в Chrome, поскольку базовая графическая реализация синхронизируется с частотой обновления экрана (поэтому вы получаете максимум 60 обновлений экрана в секунду). Измерение скорости вызова отрисовки также не будет очень полезным, поскольку система рисования Chrome помещает ваши команды рисования в буфер команд, который выполняется при следующем обновлении экрана.

Использование setTimeout для измерения производительности графики — еще одна плохая идея. Интервал setTimeout в браузерах ограничен 4 мс, поэтому максимум, что вы можете получить от него, — это 250 кадров в секунду. Исторически сложилось так, что браузеры имели разные минимальные интервалы, поэтому у вас мог быть очень неправильный тривиальный тест отрисовки, который показывал, что браузер A работает со скоростью 250 кадров в секунду (минимальный интервал 4 мс), а браузер B работает со скоростью 100 кадров в секунду (минимальный интервал 10 мс). Очевидно, что A быстрее! Нет! Вполне возможно, что B выполнил код отрисовки быстрее, чем A, скажем, A занял 3 мс, а B — 1 мс. Не влияет на FPS, так как время прорисовки меньше минимального интервала setTimeout. А если браузер отображает асинхронно, все ставки не выполняются. Не используйте setTimeout, если вы не знаете, что делаете.

Как это сделать тогда

Лучший способ протестировать — использовать реалистичную нагрузку отрисовки и умножать ее до тех пор, пока частота кадров не начнет снижаться. Например, если вы пишете игру сверху вниз с тайловой картой местности, попробуйте рисовать тайловую карту каждый кадр и посмотреть, работает ли она со скоростью 60 кадров в секунду. Если да, увеличьте нагрузку (рисуйте тайловую карту дважды в каждом кадре с очисткой между ними). Продолжайте увеличивать, пока FPS не упадет до нового стабильного уровня. Теперь вы знаете, сколько слоев тайловой карты можно нарисовать за кадр.

Разные графические приложения имеют разные потребности, поэтому при написании тестов следует учитывать это. Измерьте графические функции, которые вы используете в своем приложении. Когда вы обнаружите медленный сценарий, постарайтесь сократить его до наименьшего фрагмента кода, который его воспроизводит (и отправьте отчет об ошибке на new.crbug.com , если он должен работать быстрее).

Чтобы узнать, как писать высокопроизводительный код веб-графики, ознакомьтесь с выступлением Ната Дуки и Тома Вильциуса из команды Chrome GPU на Google I/O 2012.