Сервер считает мир тиками, 20 раз в секунду, и у каждого тика есть бюджет: 50 миллисекунд. Пока сервер укладывается, TPS ровно 20. Как только игроков становится много и тик затягивается дольше 50 мс, TPS начинает падать. Поэтому вопрос «как нам держать 20 TPS при большом онлайне» — это вопрос «из чего складывается тик и что в нём можно сократить».
В этой статье мы разбираем несколько обычных механик игры, которые на сервере с большим онлайном заметно нагружают тик, показываем, сколько каждая из них стоит, и что мы с ними сделали. У каждой находки есть замер: мы включали и выключали оптимизацию по очереди и сравнивали время тика.
1Коротко #
| Что | Было | Стало |
|---|---|---|
| Время тика при той же нагрузке (стенд с ботами) | 29,7 мс | 24,9 мс (−16,2 %) |
| Спавн мобов в тике (47 игроков) | 16–21 % | 4,5 % |
| Подсчёт мобов перед спавном | 5,7 % | 1,2 % |
| Тик на живом сервере при 37–42 игроках | 48–57 мс (14,5–19,5 TPS) | ≈ 45 мс (20 TPS) |
| Подвисания на десятки секунд | 4 за 3 часа по 41–62 с | убраны |
| Падения сервера | 4 за 6–7 октября | 0 с 7 октября |
Запас у сервера не бесконечен: сейчас 20 TPS держится примерно до 30 игроков, при 40+ игроках мы видим редкие просадки до 16 TPS. Ниже — откуда это берётся и что мы делаем дальше.
2Как мы измеряем #
Мы не доверяем «ощущениям», поэтому каждая находка проверяется A/B-тестом.
- Стенд. Отдельный сервер с копией нашего мира и 10–12 ботами. Боты играют по-настоящему: каждый стоит в одном из самых застроенных регионов мира, облетает его и меняет предметы в инвентаре. Для сервера они обычные игроки, так что работают спавн, случайные тики, отслеживание и достижения.
- Метрика. Медиана времени тика (P50, мс): половина тиков короче этого значения. Она не искажается редкими разовыми задержками.
- Порядок. Окна «выключено / включено» чередуются по схеме ABBA, чтобы дрейф нагрузки не попал в разницу.
- Живой сервер. Самые важные оптимизации мы также переключали на настоящем сервере с игроками.
3Спавн мобов: попытка каждый тик #
В ванильной игре сервер каждый тик проходит по всем чанкам вокруг каждого игрока и пытается заспавнить мобов. На проде при 47 игроках на это уходило 16–21 % времени тика.
Мы сделали так, чтобы попытка спавна выполнялась раз в 4 тика. Результат на стенде: медиана тика 27,8 → 23,9 мс (−14,0 %), и во всех четырёх кругах теста: −13,2 / −13,1 / −14,6 / −14,8 %. Это самый большой и самый ровный эффект из всех.

Выбор интервала мы тоже проверили. Спавн раз в 2 тика дал бы выигрыш поменьше: переход со «раз в 2» на «раз в 4» убирает ещё 8,4 % (25,0 → 22,9 мс), и снова во всех четырёх кругах.

На живом сервере после этой оптимизации спавн занимает 4,5 % тика вместо 16–21 %.
4Подсчёт мобов перед спавном #
Перед каждой попыткой спавна ванильный сервер заново пересчитывает всех мобов по категориям и по игрокам. Это ещё 5–6 % тика на проде. Подсчёт мы тоже делаем раз в 4 тика: новые мобы в него добавляются как обычно, а полный пересчёт происходит реже. Доля подсчёта в тике на живом сервере упала с 5,7 % до 1,2 %.
Это небольшая статья затрат: на стенде выигрыш от неё около 3 % и находится на уровне шума. Мы оставили её, потому что она ничего не ломает и убирает лишний пересчёт.
5Проверка «тикать ли эту сущность» #
Мы используем мод Does It Tick, который отключает обработку сущностей в чанках, где давно нет игроков. Для этого на каждую сущность каждый тик он спрашивал у своего счётчика, сколько времени игроки провели в соседних 9 чанках. В профиле это 8,6 % тика.
Мы добавили кэш на 200 тиков (10 секунд): время в чанке только растёт, поэтому поведение мода не меняется, а запросов к счётчику становится заметно меньше. Доля в тике упала до 3,1 %, а медиана тика на стенде — 24,6 → 22,3 мс (−9,3 %), во всех четырёх кругах.

6Достижения по инвентарю и осадки #
Две мелкие статьи ванильного тика: срабатывание достижений при любом изменении инвентаря и обработка осадок в каждом чанке. Мы сгруппировали срабатывание достижений в окно 10 тиков, а осадки обрабатываем вдвое реже. Выигрыш небольшой: −3,0 % (24,7 → 23,9 мс), в трёх кругах из четырёх. На живом сервере срабатывание достижений занимало 3,7 % тика, так что эти правки стоят того, но они не главные.
7Все оптимизации вместе #
Отдельные вклады нельзя просто перемножить: они частично перекрываются. Меньше попыток спавна означает меньше сущностей, которые потом проверяет предыдущий пункт. Поэтому мы измерили всё сразу: четыре запуска на свежем сервере по схеме «ваниль / всё включено / всё включено / ваниль».
Медиана тика 29,7 → 24,9 мс (−16,2 %), P95 (тик, дольше которого бывает только 1 из 20) 55,0 → 51,3 мс. Оба запуска «всё включено» оказались ниже обоих запусков «ваниль». Оценка по сумме отдельных вкладов давала бы около −25 %, прямой замер скромнее, и именно ему мы верим.

Что это значит в TPS. Грубо TPS равен 1000, делённым на время тика (но не выше 20):
| Время тика без оптимизаций | С оптимизациями (−16 %) | TPS без → с |
|---|---|---|
| 66 мс | ≈ 55 мс | 15 → ≈ 18 |
| 80 мс | ≈ 67 мс | 12,5 → ≈ 15 |
| 100 мс | ≈ 84 мс | 10 → ≈ 12 |
8Проверка на живом сервере #
Стенд не заменяет настоящий сервер, поэтому мы переключали оптимизации и на нём, в одно и то же время и при одинаковом онлайне.
15–20 игроков. Двенадцать окон по пять минут, онлайн в обеих фазах 18. Медиана тика 36,7 → 34,4 мс (−6,1 %). Живой сервер шумнее стенда: в четырёх кругах из шести тик стал ниже, но средняя картина совпадает.

37–42 игрока. Здесь разница самая заметная: с оптимизациями тик ≈ 45 мс (ровные 20 TPS), без них 48–57 мс (14,5–19,5 TPS). Чем больше онлайн, тем заметнее выигрыш: попыток спавна и сущностей больше, и экономия растёт вместе с ними.
9Другие находки #
Чешуйницы без лимита. Во время одного провала мы поймали, что заметная часть тика уходит на чешуйниц: в одном чанке их накопилось 63–71. Спавн из «зараженных» блоков шёл мимо общего лимита мобов. Скопление мы убрали, а лимит для таких спавнов включили (настройка infested.enforce-mobcap). Перезапуск для этого не понадобился.
Дальность деспавна монстров. В ваниле монстры исчезают на расстоянии 128 блоков от игрока. При 40 игроках тик сущностей занимал 18–22 %. Мы сократили эту дальность до 100 блоков: монстры дальше 100 блоков от всех игроков исчезают сразу, и сервер не тратит на них тик.
Сохранение на диск в главном потоке. Ванильное сохранение игроков идёт в главном потоке сервера: если диск замешкался, замирает вся игра. Мы замечали такие «фризы» по 41–62 секунды, по четыре за три часа. Теперь запись данных игроков и хранилища кораблей Sable идёт в фоновом потоке, а главный поток её не ждёт. Подвисаний дольше 5 секунд теперь около 11 за 10 часов, и самое длинное — 20 секунд; раньше их были десятки за вечер, до 95 секунд.
10Куда уходит тик сейчас #
Вот как выглядит тик главного потока при 29 игроках после всех оптимизаций:

Главная статья теперь не спавн, а механизмы Create (14,7 % тика из 20,5 % блок-сущностей) и тик сущностей (около 19 %). Общих «бесплатных» исправлений здесь не осталось: дальше нужны точечные решения.
11Сколько игроков тянет сервер #
Так выглядит сервер сегодня, со всеми оптимизациями. Мы снимали профиль каждые 15 минут и сопоставляли медиану тика с онлайном:
| Онлайн | Медиана тика | P95 | TPS |
|---|---|---|---|
| до 9 игроков | 18,6 мс | 27 мс | 20 |
| 10–19 | 32,1 мс | 41 мс | 20 |
| 20–29 | 43,0 мс | 53 мс | 20 |
| 30–39 | 54,0 мс | 72 мс | ≈ 18,5 |
| 40+ | 61,3 мс (максимум 71) | 77 мс | просадки до ≈ 16 |

Каждый игрок добавляет примерно 1 мс к тику, и 50 мс мы пересекаем около 30 игроков. Это описание, а не A/B-тест: вечером при тех же игроках нагрузка тяжелее.
12Что дальше #
Простые и безопасные исправления мы уже сделали. Остаются тяжёлые статьи тика: механизмы Create (15–22 %), тик сущностей (20–26 %), корабли Sable (около 10 %) и чанки (около 10 %). Дальше возможны два пути:
- Точечные оптимизации конкретных механизмов Create и кораблей, которые больше всего нагружают тик в реальных базах;
- Изменения геймплея: лимиты мобов, радиусы обработки Create и Sable. Это решения, которые влияют на игру, поэтому мы будем принимать их вместе с игроками.
Мы продолжим замерять каждую находку так же, как здесь, и расскажем, что получилось.