RE:NODE

Эксплуатация11 мин чтения

CPU игрового сервера: 100% на одном потоке

Почему игровой сервер лагает при 100% CPU на многоядерном тарифе, как панели считают CPU по ядрам и как самому найти основной поток, троттлинг и время тика.

0 прочтений

В игровой панели CPU считается в процентах одного ядра: 100% - это одно полностью занятое ядро, 250% - два с половиной. Большинство игровых серверов выполняют основную работу в одном главном потоке, который может использовать не больше одного ядра, поэтому сервер, стабильно показывающий 100% на тарифе с 250%, обычно не «загружен на 40%» - это главный поток, у которого кончилось время, и игроки ощущают это как лаги. Больше ядер тут ничего не дадут. Показание на самом лимите тарифа означает совсем другое: контейнер троттлится до выделенной ему доли. Отличать эти два случая друг от друга и от здоровой нагрузки - в этом и состоит всё умение читать график CPU игрового сервера, и когда знаешь, куда смотреть, на это уходит около минуты.

Эта статья о том, как читать цифру. Чего докупать - CPU или памяти, - разобрано в статье CPU или RAM: что тормозит ваш сервер, а как хостер делит физический CPU между клиентами - в статье общий CPU и шумные соседи.

Как считается процент CPU#

Для процента CPU есть два соглашения, и при одной и той же нагрузке они дают совершенно разные числа.

СоглашениеКто используетЧетыре занятых ядра на 8-ядерной машине
Процент одного ядраtop в Linux, Docker, Pterodactyl и большинство игровых панелей400%
Процент всей машиныДиспетчер задач Windows, многие облачные дашборды50%

Игровые панели используют первое. Сервер с лимитом 250 может показывать от 0% до 250%, и это число прямо означает «сколько ядер работы выполнено за эту секунду». В каталоге RE:NODE лимит указан так же: cpu - это процент одного ядра и жёсткий лимит, так что тариф с 2.5 vCPU - это потолок в 250%.

Соглашение важно, потому что люди, пришедшие с рабочего стола Windows, читают 100% как «выжат до предела», а 25% - как «запаса полно». В панели 100% на тарифе с 250% может оказаться худшим показанием на графике, а 250% - вполне нормальным.

Почему большинство игровых серверов однопоточны там, где это важно#

Игровой сервер крутит цикл. Каждый его проход - тик - читает ввод игроков, двигает каждую сущность, выполняет ИИ, рассчитывает физику и бой и отправляет результат обратно. Тик должен уложиться в фиксированный бюджет времени, чтобы игра шла с задуманной скоростью.

ИграЦелевая частотаБюджет на тик
Minecraft20 тиков в секунду50 ms
Counter-Strike 264 тика в секунду15.6 ms
Factorio60 обновлений в секунду16.7 ms
Terraria60 обновлений в секунду16.7 ms
Игры на Source с 66 тиками (TF2, Garry's Mod по умолчанию)66 тиков в секунду15 ms

Работа внутри тика в основном последовательна: ход зомби зависит от того, куда пошёл игрок, а это зависит от полученного ввода, который нужно обработать по порядку. Игровые движки могут выносить и выносят часть работы в другие потоки - генерацию чанков и освещение в Minecraft, сохранение, сеть, поиск пути в некоторых играх на Unity, физику в некоторых играх на Unreal, - но основная симуляция живёт в одном потоке. Когда этому потоку нужно больше бюджета, сервер отстаёт, и никакое количество простаивающих рядом ядер не поможет.

Поэтому для игрового хостинга важнее всего однопоточная скорость - насколько быстро одно ядро справляется с одним потоком работы, - и поэтому статья что на самом деле значит tick rate хорошо дополняет эту.

Как читать график: четыре формы#

С учётом соглашения и тика график CPU игрового сервера принимает одну из четырёх форм.

Низкий и с пиками

В среднем намного ниже 100%, с пиками, когда заходят игроки, генерируются чанки или сохраняется мир. Это здоровая картина. Пик сохранения до 150% на две секунды - это фоновый поток, который делает свою работу, и именно для этого и нужны дополнительные ядра.

Ровно около 100% на тарифе с большим запасом

Сервер стабильно показывает 95-105% на тарифе, который позволяет 200% или 300%. Это самый важный случай. Почти всегда он означает, что главный поток непрерывно занимает целое ядро - он никогда не простаивает между тиками, потому что никогда не заканчивает тик раньше срока. Игроки видят лаги, откаты позиции или падение tick rate. Решение - меньше работы на тик или более быстрое ядро, а не больше ядер.

Есть и безобидный вариант: некоторые движки между тиками крутятся в активном ожидании, а не спят, и поэтому показывают почти целое ядро даже в простое. Если график стоит на 100%, когда никого нет онлайн, а собственные метрики тиков игры идеальны, это особенность движка, а не проблема.

Ровно на лимите тарифа

График прижат ровно к лимиту - 250% на тарифе с 250% - и линия сверху ровная, будто срезана ножом. Контейнер просит больше CPU, чем ему разрешено, и его троттлят. Каждый поток, включая главный, на часть каждого периода планирования ставится на паузу. Вот в этом случае больше CPU в тарифе действительно помогает - или нужно найти, что занимает все эти потоки: часто это генерация мира, рендер карты или плагин со своим пулом потоков, который ведёт себя неправильно.

На RE:NODE сервер, прижатый к лимиту, просто медленный, а не в беде: CPU жёстко ограничивается купленной долей, и за 100% от выделенного ресурса сервер никогда не приостанавливают.

Постепенный рост в течение нескольких дней

Медленный подъём, который сбрасывается только рестартом, сам по себе не проблема CPU. Обычно что-то накапливается - сущности, выпавшие предметы, растущий список, который плагин перебирает каждый тик, - а кривая CPU лишь симптом. Найдите то, что растёт; сторона той же картины, связанная с памятью, описана в статье утечки памяти на игровом сервере.

Как самому найти главный поток#

График в панели - это сумма по всем потокам. Чтобы увидеть, не упёрся ли в потолок один поток, нужны цифры по потокам. С shell на своём сервере или VDS:

bash
# per-thread view of one process; press H in top to toggle threads$ top -H -p "$(pgrep -f server.jar)"# a one-off list of threads sorted by CPU$ ps -L -o tid,pcpu,comm -p "$(pgrep -f server.jar)" --sort=-pcpu | head# per-thread CPU every second (needs the sysstat package)$ pidstat -t -p "$(pgrep -f server.jar)" 1

В Minecraft главный поток называется Server thread; в игре на Unity это обычно первый поток процесса; в сервере на Source это сам процесс, рядом с которым очень мало других потоков. Если один поток держится на 95-100%, а остальные низкие, сервер упирается в главный поток, что бы ни показывала сумма.

Без shell - а в панели это обычная ситуация - путь лежит через собственные инструменты игры. Лучшие у Minecraft: spark (входит в свежие сборки Paper, в остальных ставится плагином) показывает CPU по потокам и профиль того, чем именно был занят главный поток. Разбор такого отчёта - в статье как читать отчёт spark.

Собственные цифры игры лучше графика CPU#

График CPU показывает, насколько занята машина. Игрокам важно, укладываются ли тики вовремя, и почти каждая игра сообщает об этом напрямую.

ИграКоманда или инструментЗдоровое значение
Minecraft (Paper)/mspt, /tps, sparkMSPT ниже 50, TPS 20
Игры на Sourcestats в консоли сервераFPS не ниже tick rate
Rustfps в консоли сервераБлизко к целевому server.fps, без падения
FactorioUPS в отладочном оверлее клиента60
FiveMresmon в клиенте, график производительности txAdminРедкие подвисания потока сервера
Серверы на UnrealFPS сервера, если игра его показывает, иначе отзывы игроковСтабильно

MSPT - миллисекунды на тик - самый наглядный из этих показателей. Сервер Minecraft на 20 TPS может тратить 5 ms из своих 50 ms или 49 ms, и число TPS эти случаи не различает. MSPT различает: 45 ms означают, что до лагов один оживлённый вечер, что бы ни показывал график CPU. Если ваша игра даёт показатель на тик, следите за ним, а не за процентом CPU.

Троттлинг и как его доказать#

В контейнере лимит CPU обеспечивает контроллер CPU ядра. В cgroups v2 лимит и счётчики троттлинга видны изнутри контейнера, если у вас есть shell, например на VDS с Docker:

bash
$ cat /sys/fs/cgroup/cpu.max250000 100000$ cat /sys/fs/cgroup/cpu.statusage_usec 81234567890user_usec 70123456789system_usec 11111111101nr_periods 4211230nr_throttled 18822throttled_usec 912345678

cpu.max читается как «250 000 микросекунд CPU на период в 100 000 микросекунд» - два с половиной ядра. В cpu.stat счётчик nr_throttled считает периоды, в которых контейнер упёрся в этот потолок и был поставлен на паузу до следующего. Разделите на nr_periods, чтобы получить долю: здесь она меньше половины процента, то есть это шум. Доля в несколько процентов в часы пик, совпадающая с моментами лагов, - это настоящий троттлинг. Быстрый рост throttled_usec, пока игроки жалуются, - та же история, выраженная во времени.

Троттлинг плохо сочетается с играми на тиках, потому что он рваный. Сервер, который израсходовал всю квоту за первые 70 ms периода в 100 ms, потом стоит на паузе 30 ms, и тик, которому нужно было 20 из этих миллисекунд, приходит с опозданием. Поэтому сервер может в среднем показывать намного меньше лимита и всё равно подтормаживать: короткие всплески фоновых потоков исчерпывают квоту, и главный поток ждёт.

Что на самом деле делать с высокой загрузкой CPU#

Когда понятно, какой у вас случай, решение следует из него.

Упор в главный поток (ровно около 100%). Уменьшите работу на тик. Это зависит от игры и обычно даёт больше всего:

  • Minecraft: снижайте simulation-distance раньше, чем view-distance, ограничьте сущности и редстоун в конфигах Paper, предгенерируйте мир, чтобы чанки не генерировались во время игры, - см. руководство по оптимизации Paper.
  • Valheim: меньше элементов построек и терраформинга в одном месте; нагрузка сосредоточена там, где собираются игроки.
  • Rust: время кадра сервера определяют количество сущностей и размер карты, а не число игроков.
  • Factorio: UPS мегабазы - это задача проектирования, а не хостинга: меньше манипуляторов, конвейеров и кусак на тик.
  • Source: более низкий tick rate, где игра это позволяет, меньше ботов, меньше плагинов, цепляющихся за каждый кадр.

Если работы и так разумное количество, остаётся только более быстрое ядро. Больше ядер не помогут.

Троттлинг на лимите. Что-то занимает много потоков одновременно. Частые причины - предгенерация мира (Chunky в Minecraft на полной скорости использует несколько потоков), рендеры карт вроде Dynmap и BlueMap, сжатие во время backup и плагины со своими пулами. Перенесите тяжёлые задачи на тихие часы, ограничьте число их потоков, где это возможно, или перейдите на тариф выше. Переход на RE:NODE меняет лимит на том же сервере; ничего не пересобирается.

Пики, но игроки жалуются. Проверьте, совпадают ли пики с сохранениями, backup или задачами по расписанию. Backup, сжимающий большой мир, может ненадолго занять все ядра, которые позволяет тариф, а сохранение большого мира Valheim или Minecraft блокирует главный поток на всё своё время. Перенесите это на тихие часы, а для Valheim обдумайте компромисс с интервалом сохранения, описанный в руководстве по серверу Valheim.

Разобранный пример#

Сервер Paper на двадцать игроков на тарифе с лимитом 300%. Жалобы на лаги каждый вечер примерно с восьми часов.

  1. График в панели показывает 105-115% с 20:00 до 23:00 и 30-40% днём. До лимита далеко, значит, это не троттлинг.
  2. /mspt в 21:00 показывает в среднем 48 ms с пиками до 90. Главный поток на пределе бюджета.
  3. Профиль spark показывает, что 40% времени тика уходит на тик сущностей, в основном в двух чанках, и 15% - на воронки.
  4. Эти два чанка - ферма мобов и зал разведения жителей, оба построены на прошлой неделе.
  5. Лимиты сущностей на чанк в Paper и изменение частоты воронок снижают MSPT до 28 ms в пик. График CPU вечером теперь держится около 70%.

Тариф с большим числом ядер ничего не изменил бы ни на графике из шага 1, ни для игроков, потому что проблема всегда была в одном потоке. Тариф с более быстрым ядром немного помог бы и каждый месяц стоил бы дороже, пока существует ферма.

FAQ#

Почему сервер лагает, если CPU всего 100% из 300%?

Потому что 100% - это одно полностью занятое ядро, а главный поток игры может использовать только одно ядро. У потока кончилось время, а два других ядра простаивают, потому что симуляцию нельзя на них разделить. Уменьшите работу на тик или перейдите на более быстрое ядро.

Что нужно игровому серверу - больше ядер или более быстрый CPU?

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

Приостановит ли хостер сервер за 100% CPU?

На RE:NODE - нет. CPU жёстко ограничивается купленной долей, так что сервер на лимите просто работает медленнее. Это повод посмотреть, что занимает CPU, а не нарушение со стороны аккаунта.

Почему сервер использует CPU, когда никого нет онлайн?

Большинство игр продолжают тикать и пустыми: сущности, посевы, погода и ИИ в загруженных областях продолжают работать. Некоторые движки к тому же активно ждут между тиками. Низкая стабильная нагрузка в простое - это нормально; нагрузка в простое около целого ядра, когда никто не подключён, стоит сверить с собственными показателями тиков игры.

Процент CPU в панели - то же самое, что в диспетчере задач?

Нет. Панель считает в процентах одного ядра, так что 200% - это два ядра. Диспетчер задач считает в процентах всей машины. Одна и та же нагрузка может показывать 200% в панели и 25% в диспетчере задач.


Комментарии

Полностью анонимно: без аккаунта, без почты, без cookie. Мы храним имя, которое вы ввели, текст и время - больше ничего. Количество ссылок ограничено, разметка не отображается.

0/2000