Почему ваш Ryzen 9 не тянет 1.21: вскрытие мифов об оперативной памяти и ядрах
Каждый месяц на админских форумах появляется один и тот же пост:И где то в ответах обязательно появляется человек с магическим конфигом, который "фиксит всё".У меня Ryzen 9, 64 ГБ RAM, NVMe, но TPS падает до 10. Что еще подкрутить в paper.yml?
Спойлер: нет
Minecraft не оптимизируется шаманством в YAML. Он оптимизируется пониманием архитектуры JVM и самого игрового цикла. Давайте разберём три главных мифа, которые ломают сервера быстрее, чем толпа игроков с фермой воронок.
Проблема одного ядра: почему 16 ядер почти бесполезны
Первое что нужно понять: Minecraft - это последовательный игровой цикл (Game Loop). Этот цикл выполняется 20 раз в секунду. Каждый тик должен уложиться примерно в50 ms. Если тик занимает 120 ms то TPS падает примерно до ~8. И вот здесь ключевой момент.Большая часть этой логики выполняется в одном потоке.
Причины архитектурные:
- Состояние мира мутабельно
- Куча зависимостей между блоками
- Редстоун требует строгой последовательности
Да, есть вспомогательные потоки:
- Network Threads
- Chunk IO
- Region File Loading
- Async Tasks плагинов
Поэтому важна не сумма ядер, а скорость одного
16 медленных ядер не спасут. Minecraft любит высокий IPC, высокий Boost Clock, большой L3 cache, фактически сервер ведет себя как старое однопоточное приложение 2008 года, чем собственно он и является.Миф о RAM: почему 32 ГБ делают только хуже
Любимая ошибка админов: Flags:
-Xms32G
-Xmx32GНа практике происходит обратное. Причина всему: Garbage Collector. Minecraft работает на JVM, а значит память очищается GC. Когда куча большая, GC делает две неприятные вещи:Больше памяти = меньше лагов.
- сканирует больше памяти
- делает длиннее Stop-The-World паузы
Что происходит при 32 ГБ heap
GС пауза может занять180 ms если это Pause Young (Normal) (G1 Evacuation Pause), а иногда 2.4 seconds если это Pause Full GC. Для Minecraft это катастрофа. Потому что: 50 ms = 1 тик, 2 секунды = 40 пропущенных тиков. Игроки видят это как: телепорты, фризы, умирание сервера.Если сервер требует 20+ ГБ то у вас:
- Либо утечка памяти
- Либо плагин-монстр
- Либо фермы из 10000 сущностей
Хостинги и магия 8 ядер
Теперь любимая маркетинговая история хостингов. В панели мы видим:CPU 8 cores, RAM 32 GB. Звучит мощно, но на деле вы часто сидите на перепродаваемом VPS. Что это значит? Это один физический CPU который делится на 20-50+ клиентов, и тут появляется показатель, о котором админы почти не знают.CPU Steal Time
Steal Time - это время, когда ваш VM хочет использовать CPU, но гипервизор отдаёт его другому клиенту. Для Minecraft это смертельно, потому что тик может ждать процессор.Симптомы Steal Time:
TPS падает, но использование процессора низкое, оперативная память свободна, тайминги чистые. Админ начинает урезать мобов, уменьшать дистанцию симуляции, ломать геймплей, хотя проблема не в сервере вообще. А в том, что соседний VPS испытывает большую нагрузку, это может быть что угодно, от генерации нового мира до рендера 4K видео.
Вывод (который обычно игнорируют)
Minecraft сервер - это не вопрос сколько RAM и сколько ядер, это задача задержки одного потока. TPS складывается из производительности одного ядра + GC пауз + сложности мира, а не от RAM + ядер. Но магические цифры в конфигах продавать проще.
Диагностика как искусство: читаем Spark Call Tree, а не гадаем на кофейной гуще
Типичная сцена на админском форуме:Ответ обычно звучит так:TPS 11, тайминги чистые, RAM 24 ГБ, CPU 30%. Что подкрутить?
Это примерно как лечить двигатель машины уменьшением громкости радио. Если вы хотите реально понимать, почему сервер лагает, вам нужен один инструмент: Spark. Но 90% админов используют его примерно на уровне:Попробуй уменьшить entity-activation-range.
Давайте поговорим о том, где на самом деле лежит правда.О, тут есть график!
Overview - красивая игрушка для новичков
Когда вы открываете репорт spark, на первой вкладке Overview есть красивые проценты: Entity Tick, Block Tick, Plugins, Misc. Новичок смотрит на это и делает вывод:Проблема в том, что Overview - это агрегированная статистика. Они ничего не говорит о причине. Это примерно как увидеть вАга, Entities много. Нужно их уменьшить.
top: java 120% CPU. Спасибо, капитан.Call Tree - место, где начинается настоящая диагностика
Если вы хотите понять понять почему происходит нагрузка - открывайте Call Tree. Это буквально дерево вызовов JVM. Каждая строка показывает: кто вызвал функцию, сколько времени она заняла.Пример (упрощённо):
CallTree:
MinecraftServer.tickServer
└─ ServerLevel.tick
└─ Level.tickEntities
└─ Villager.tick
└─ Brain.tick
└─ BehaviorGate.tryStartEntity Tick и настоящая причина лагов
В Overview вы увидите: Entity Tick 40%. Новичок думает:Но открываем дерево вызовов, и внезапно видим:Мобов слишком много.
CallTree:
Level.tickEntities
└─ Villager.tick
└─ Brain.tick
└─ AcquirePoiДругой частый убийца - Pathfinding
Call Tree может выглядеть так: CallTree:
Mob.tick
└─ PathfinderMob.tick
└─ PathNavigation.moveTo
└─ PathFinder.findPathHopper Storm: скрытый ад серверов
Еще один частый сценарий. В Call Tree вы видите: CallTree:
HopperBlockEntity.tick
└─ tryMoveItemsСкрытый враг: IO Wait
Иногда Call Tree выглядит странно. Вы видите: CallTree:
MinecraftServer.tickServer
└─ RegionFile.write CallTree:
ChunkStorage.writeСимптомы IO проблем
На Linux смотрим
top или лучше htop и ищем показатель wa это IO Wait. Если там 10%+, то диск начинает тормозить сервер.Частые причины
- Медленный VPS SSD
- Перегруженный NVMe у хостинга
- World AutoSave
- Огромные Region файлы
Async Profiler: уровень хардкор
Если вы хотите реально понимать сервер, используйте Spark так:Это включает async-profiler. Почему это важно? Обычный Profiler JVM видит только Java Stack. Async Profiler видит: Java, C++, Kernel, System Calls. То есть вы начинаете видеть такие вещи: epoll_wait, pthread_cond_wait, write, futex. И внезапно становится понятно: сервер не грузит CPU, он ждёт систему./spark profiler start --engine async
Почему это важно
Потому что иногда проблема выглядит так: TPS: 12, CPU: 40%, RAM: свободна. Админ думает:А Spark показывает: 80% времени сервер ждёт чтение/запись диском. И всё. Никакие оптимизации AI не помогут вообще.Наверное много мобов.
JVM 21, ZGC и конец эпохи флагов Айкара: как должен выглядеть современный запуск
Если вы администрируете Minecraft достаточно давно, то наверняка видели самый копируемый набор флагов в истории серверов: Aikar Flags. Их копировали с Reddit, с Spigot, из гайдов 2018 года, из сотен Discord серверов. Проблема в том, что эти флаги писались примерно для Java 8 / 11 эпохи Paper 1.12. Сегодня мы живём в другой реальности: Java 21+, новые GC, другая модель памяти, другие профили нагрузки. И старые флаги иногда не оптимизируют сервер. Они ломают работу JVM.Прощание с G1GC (и магическими флагами)
Исторически Minecraft использовал G1GC, почему? Потому что в 2016-2018 он был единственным адекватным сборщиком мусора с низкими паузами в HotSpot. Отсюда и родились знаменитые флаги: Bash:
-XX:+UseG1GC
-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40
-XX:G1HeapRegionSize=8Mjava 21 + флаги 2017 годаМинималистичный современный запуск
Сегодня нормальный запуск выглядит примерно так: Bash:
java \
-Xms10G \
-Xmx10G \
-XX:+UseZGC \
-jar paper.jarZGC: почему паузы стали микроскопическими
Главная причина отказаться от старого подхода - это новые Garbage Collectors. Один из них - ZGC. Идея ZGC радикально отличается от старых GC. Классическая модель: stop-the-world, mark, compact, resume. То есть: сервер замер, GC делает работу, сервер оживает. ZGC делает иначе. Он выполняет почти всё параллельно с приложением. То есть: marking работает одновременно с игрой, relocation тоже, pause остаётся только для коротких синхронизаций. В результате паузы становятся примерно 0.3-1.5 ms, для Minecraft это практически незаметно. Напомню: 1 тик = 50 ms. То есть GC теперь меньше 3% одного тика. Для старых GC 100-300 ms паузы были нормой.Важная оговорка
GC не лечит плохую архитектуру сервера. Если у вас 1000 сущностей, 1000 воронок и 1000 предметов валяющихся на земле, никакой ZGC не спасёт TPS. Он лишь уберёт GC лаги, а не игровую нагрузку.Современные ядра: почему Paper - это только начало
Следующая ошибка админов:Нет. Paper - это база. Но сейчас существуют ядра, которые делают более агрессивную оптимизацию тиков. Самые известные:Я поставил Paper. Теперь всё оптимизировано.
- Pufferfish
- Purpur
Dynamic Activation Buffer: почему это умнее, чем "удалить мобов"
Классическая оптимизация завязана наentity-activation-range, то есть мобы далеко от игрока перестают тикаться. Но это очень грубый механизм. Он ломает: фермы, искусственный интеллект, поведение мобов. DAB работает иначе. Он делает динамический бюджет тиков. Упрощённо: сервер смотрит сколько времени осталось до 50 ms, и если времени мало, он адаптивно уменьшает активность сущностей. Не всех. А только тех, которые: далеко, менее важны, не взаимодействуют с игроками. В результате: важные мобы продолжают тикаться, второстепенные замедляются. И сервер держит TPS стабильно. Это гораздо ближе к тому, как реальные игровые движки управляют нагрузкой.Маленькая правда о "плохих плагинах"
Никакая оптимизация ядра не спасёт сервер, если плагин делает O(n2) обходы, или синхронные SQL запросы в основном тике. Call Tree в spark иногда выглядит так: CallTree:
Plugin.tick
└─ Database.query
└─ mysql socket waitЗолотые правила админа сервера
После 10 лет возни с JVM и Minecraft можно сформулировать несколько простых правил.- TPS убивает не RAM, а задержки одного потока.
- GC должен быть простым, сегодня это ZGC или Shenandoah, а не археология из 2017 года.
- Профилирование важнее конфигов, всегда сначала профайлер spark и дерево вызовов, а уже потом настройки.
- Мир - главный источник нагрузки, TPS чаще всего убивают фермы мобов, поиск путей, воронки, массивная загрузка чанков, а не
paper.yml.
Финальная мысль
Оптимизация Minecraft сервера это не поиск магического числа в конфиге. Это системная задача, она включает в себя:- Понимание JVM
- Понимание Задержки CPU
- Анализ Spark профайлера
- Анализ Ввода/Вывода
- Анализ Игровой логики