От 40 до 140 FPS: искать причину, а не симптом
Однажды игра начала выдавать 40 FPS. Раньше такого не было, железо не менялось, а обновление драйвера не должно было дать такую разницу.
Первое, что я сделал, — то же, что сделал бы любой: понизил разрешение. Перешёл с 1440p на 1080p, включил апскейлер — и получил 200 FPS. Проблема «решена».
Но это не было решением. Это было заглушение симптома. Монитор я брал ради 1440p, а не чтобы гонять его в 1080p. И главное — я не знал, почему так вышло. То, чего вы не поняли, обязательно вернётся.
Эта статья именно об этом: о разнице между «закрыть неисправность» и «найти причину». Пример из игры, но метод применим к любой производственной проблеме.
Почему ответа «заработало» недостаточно
То, что понижение разрешения помогло, дало мне одну информацию: узкое место — в пиксельной работе. Полезно, но недостаточно, потому что вопрос остаётся открытым: почему объём пиксельной работы вдруг вырос? Разрешение-то не менялось.
В разработке всё так же. «Добавил retry, теперь не падает» — это не исправление. Это способ сделать ошибку незаметной для счётчика. Причина остаётся на месте и возвращается в другой форме.
Поэтому я отступил назад и переформулировал вопрос: кто приказывает рисовать столько пикселей?
Первое измерение: где узкое место
Сначала я посмотрел на GPU. Цифры вышли такие:
мощность темп. загрузка видеопамять FPS
1440p 58W 84C 99% 3753 MB 40
1080p+FSR 34W 78C 64% 3409 MB 200Самый важный столбец — видеопамять. Она почти не изменилась: 3753 и 3409 МБ. То есть память узким местом не была. А загрузка упала с 99% до 64%.
Вместе эти два числа дают чёткий ответ: GPU упирался не в память, а в вычислительную работу. То есть он действительно рисовал слишком много пикселей.
Это самый полезный шаг в отладке: измерять до того, как строить догадки. Гипотеза «не хватает памяти» была опровергнута минутным измерением и развернула меня в совершенно другую сторону.
Второе измерение: сколько пикселей он рисует на самом деле
Если GPU рисует слишком много пикселей, нужно узнать, сколько именно. Я спросил у системы реальный размер окна — и ответ оказался неожиданным.
Мой монитор — 2560x1440. Система же показывала его так:
$ xrandr --listmonitors
0: +*HDMI-A-1 4480/597x2520/336+2560+0
Screen 0: current 7040 x 25204480x2520. То есть 11,3 мегапикселя — втрое больше, чем 1440p. В полноэкранном режиме игра рисовала именно столько, а система потом сжимала картинку до 1440p. Вся лишняя работа уходила впустую.
Вот здесь всё встало на свои места. 40 FPS не были неправильным числом. Для втрое большего объёма работы это было ровно правильное число.
Причина: одна глобальная настройка
Дальше было просто. В ноутбуке два экрана: внутренний с высокой плотностью, для него выставлен масштаб 1.75, и внешний монитор — обычный, без масштабирования.
Композитор использует для старых X11-приложений один общий масштаб и выбирает наибольший — то есть 1.75. Это значение распространяется и на монитор, которому масштаб не нужен. В результате внешний монитор видится старым приложениям не как 2560x1440, а как 4480x2520.
А игра запускалась именно в этом старом режиме — так был настроен её собственный стартовый скрипт.
Причина такая: масштаб внутреннего экрана заставлял игру на внешнем мониторе выполнять втрое больше работы.
Решение и почему я выбрал второй вариант
Путей было два.
Первый — запускать игру полностью в современном режиме, минуя старый слой. FPS восстанавливался, но появлялся побочный эффект: при двух мониторах игра всегда открывалась не на том экране, а её внутренняя настройка выбора монитора переставала работать.
Второй — опустить глобальный масштаб до 1, то есть заставить систему самой увеличивать старые приложения. После выхода из сессии и повторного входа: с 40 FPS до 140.
Я выбрал второй. У него есть цена — на экране ноутбука старые приложения слегка размываются. Но эта цена для меня оправдана, потому что решение чинит не одну игру, а сразу все старые приложения.
Это тоже часть отладки: выбирают не самое красивое решение, а то, у которого меньше побочных эффектов.
Следующее узкое место
После исправления я измерил снова — и увидел второе ограничение: процессор при 94-97 градусах троттлит по 524 миллисекунды каждые три секунды. То есть теперь упор не в GPU, а в охлаждение.
Это нормально. Открыв одно узкое место, вы увидите следующее. Важно каждый раз подтверждать измерением, а не догадкой.
Метод
Из этой истории стоит унести не игровые настройки, а порядок действий:
- То, что временное решение сработало, — это информация, а не решение. Оно лишь указывает, где узкое место.
- Измеряйте прежде, чем предполагать. Моя гипотеза «не хватает памяти» была отброшена за минуту.
- Спрашивайте, что думает система, а не что знаете вы. Мой монитор 1440p, но система считала его 4480x2520 — весь ответ был в этом расхождении.
- Найдя причину, выбирайте решение по побочным эффектам.
- После исправления измерьте снова. Следующее узкое место есть всегда.
В разработке всё работает так же. Медленный API, растущая память, ошибка, которая появляется через раз — везде задаётся один и тот же вопрос: я закрываю симптом или нашёл причину?
Если вы не можете ответить, проблема всё ещё на месте.