Число кадров в секунду — величина усреднённая по секунде, и в этом её главный недостаток. Плавность воспринимается не по количеству кадров, а по равномерности интервалов между ними. Секунда, в которой все кадры пришли через равные промежутки, и секунда, где несколько кадров задержались на десятки миллисекунд, а остальные пришли пачкой, дают одинаковое среднее и совершенно разное ощущение при просмотре.
Время кадра вместо частоты кадров
Корректная величина для анализа — время кадра, то есть интервал между появлениями соседних кадров на экране. Ряд таких интервалов — это то, что глаз реально видит. Если интервалы держатся стабильно, картинка воспринимается плавной даже на умеренной частоте. Если в ровном ряду возникает одиночный интервал в несколько раз длиннее соседних, он читается как рывок, независимо от того, сколько кадров было выдано в целом за секунду.
Отсюда практика смотреть на распределение, а не на среднее: анализируют худшие проценты интервалов — тот хвост распределения, куда попадают самые долгие кадры. Именно этот хвост описывает провалы. Среднее по определению устойчиво к редким выбросам: несколько длинных кадров на сотню коротких почти не сдвигают его, но полностью формируют впечатление от сцены.
Откуда берутся длинные кадры
Причины делятся на несколько семейств, и различать их важно, потому что лечатся они по-разному.
Первое семейство — подгрузка данных. Когда сцена требует текстур или геометрии, которых нет в видеопамяти, их нужно перенести из системной памяти или прочитать с накопителя. Перенос по шине занимает время, и кадр, который ждёт данных, растягивается. Если объём видеопамяти близок к исчерпанию, такие переносы становятся регулярными, и провалы выстраиваются в характерный рисунок: серия ровных кадров, затем один длинный, снова серия. Проверяется это косвенно — по тому, что при снижении разрешения текстур рисунок исчезает.
Второе — компиляция шейдеров. Графический конвейер переводит шейдер в машинный код для конкретного GPU при первом использовании. Пока идёт компиляция, кадр не может быть завершён. Поэтому рывки густо сидят в начале сцены или при первой встрече с новым эффектом и затем пропадают: результат попадает в кэш. При смене драйвера кэш сбрасывается, и всё повторяется — это нормальное поведение, а не деградация.
Третье — упор в процессор. Кадр готовится в два этапа: центральный процессор формирует список команд, видеокарта его исполняет. Если поток подготовки не успевает, видеокарта простаивает в ожидании работы, и длительность кадра определяется процессором. Признак — низкая загрузка GPU при высокой загрузке одного-двух ядер. Различие между скоростью одного ядра и общим числом ядер здесь принципиально, и об этом подробнее в разделе про процессоры.
Сброс частот как источник плавных, но заметных провалов
Отдельный случай — снижение частот самой видеокартой. Плата постоянно балансирует между тремя ограничителями: температурой, лимитом мощности и допустимым напряжением. Когда радиатор прогревается или потребление упирается в лимит, контроллер уменьшает частоту ядра. Это не одиночный длинный кадр, а плавное удлинение всех интервалов подряд, поэтому среднее падает, а рывков не появляется. Такой провал выглядит иначе: производительность после десятков минут работы устойчиво ниже, чем в первые минуты, при неизменной сцене.
Признак теплового ограничения — температура ядра, упирающаяся в один и тот же потолок, при вентиляторах на максимальных оборотах. Признак ограничения по мощности — потребление, стоящее ровно на лимите, при температурах ниже порога. Различить их можно по тому, меняется ли поведение после улучшения продува корпуса.
Синхронизация и то, что происходит на границе
Ещё один слой — взаимодействие с монитором. Экран обновляется с фиксированной или переменной частотой, и кадр, готовый на миллисекунду позже момента обновления, ждёт следующего. При жёсткой синхронизации это превращает небольшое опоздание в удвоенный интервал: вместо чуть более долгого кадра получается ровно два периода. Так одна и та же нагрузка при включённой и выключенной синхронизации даёт разный характер провалов при одинаковом среднем.
Переменная частота обновления смягчает эффект, подстраивая период под готовность кадра, но только внутри своего диапазона. Если частота выходит за нижнюю границу диапазона, монитор переключается на кратное повторение кадров, и на этой границе поведение снова становится ступенчатым. Это объясняет, почему провалы иногда концентрируются вокруг определённого значения частоты, а не распределены равномерно. Характеристики диапазонов и время отклика разбираются в разделе про мониторы.
Как измерять, чтобы увидеть картину
Полезнее всего писать лог времени кадра и смотреть его как график, а не как одно число. На графике видны и одиночные пики, и ступенчатые сдвиги, и медленный дрейф от нагрева — три разных явления, которые в среднем показателе сливаются в одну цифру. Прогон должен быть достаточно длинным: короткий тест на две минуты не успеет прогреть радиатор и не покажет сброс частот, а прогон по одному участку сцены не поймает подгрузку данных при переходе в другую зону.
Второе условие — повторяемость. Одна и та же сцена, один и тот же маршрут, одинаковые настройки. Иначе разница между прогонами будет объясняться содержимым сцены, а не состоянием системы. И третье: полезно фиксировать рядом с временем кадра загрузку GPU, загрузку ядер процессора, занятость видеопамяти, температуры и потребление. Само по себе время кадра говорит, что провал был; сопутствующие показатели говорят, какой из механизмов его вызвал.