Сборки серверов

СливПлатные

Сейчас онлайн

  • He1ly03
  • iip0chka
  • CleanHealer
  • iluha_2013
  • Ilya1239718
  • KristianKernel
  • biubiukawa
  • mikebadatlife
  • StarKiing
  • darksoullx_
  • DEFN1_CHEAK
  • akamme
  • MaoxFeed
  • S1N
  • MrLondix
  • Vova123456789co
  • jhgfjhjl
  • Dragon725
  • Vadimkkkaa
  • RRRRaiso1
  • 123k3883bebra
  • sova1n
  • tor23
  • kira33513
  • codh
  • RedFoxy545
  • Mortoma20
  • feyhoa
  • Hyper_Cat
  • patrickreseller
  • Zhenek123
  • brandonTALENT
  • Bismark1934
  • fcPlugins
  • accauntdianlo7272
  • amogusinalisaya
  • flaer155
  • cesar111
  • Liger213
  • popkanevko
  • ThevillainGG
  • Scyth3
  • 334fdsgassff535512332342
  • dirtysonic
  • Adwjsjdj
  • Yureckiy1
  • makar14
  • Matviy291382
  • AnrimiX
  • Soldi_n
  • Skyns1
  • fundamentalzola
  • kidVangan
  • fried_mester
  • Kodolov
  • leo_brat
  • srfef
  • sonic928391

Почему ваш Ryzen 9 не тянет 1.21

Почему ваш 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. И вот здесь ключевой момент.

Большая часть этой логики выполняется в одном потоке.
Причины архитектурные:
  1. Состояние мира мутабельно
  2. Куча зависимостей между блоками
  3. Редстоун требует строгой последовательности
Поэтому Minecraft нельзя просто "раскидать по ядрам".
Да, есть вспомогательные потоки:
  1. Network Threads
  2. Chunk IO
  3. Region File Loading
  4. Async Tasks плагинов
Но основной тик - узкое место с одним потоком.

Поэтому важна не сумма ядер, а скорость одного​

16 медленных ядер не спасут. Minecraft любит высокий IPC, высокий Boost Clock, большой L3 cache, фактически сервер ведет себя как старое однопоточное приложение 2008 года, чем собственно он и является.

Миф о RAM: почему 32 ГБ делают только хуже​

Любимая ошибка админов:
Flags:
-Xms32G
-Xmx32G
Логика звучит красиво:
Больше памяти = меньше лагов.
На практике происходит обратное. Причина всему: Garbage Collector. Minecraft работает на JVM, а значит память очищается GC. Когда куча большая, GC делает две неприятные вещи:
  1. сканирует больше памяти
  2. делает длиннее Stop-The-World паузы
Stop-The-World это буквально когда JVM останавливает весь сервер. Никаких тиков, никаких пакетов, ничего.

Что происходит при 32 ГБ heap​

GС пауза может занять 180 ms если это Pause Young (Normal) (G1 Evacuation Pause), а иногда 2.4 seconds если это Pause Full GC. Для Minecraft это катастрофа. Потому что: 50 ms = 1 тик, 2 секунды = 40 пропущенных тиков. Игроки видят это как: телепорты, фризы, умирание сервера.

Если сервер требует 20+ ГБ то у вас:
  1. Либо утечка памяти
  2. Либо плагин-монстр
  3. Либо фермы из 10000 сущностей
GC тут не виноват.

Хостинги и магия 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%. Что подкрутить?
Ответ обычно звучит так:
Попробуй уменьшить entity-activation-range.
Это примерно как лечить двигатель машины уменьшением громкости радио. Если вы хотите реально понимать, почему сервер лагает, вам нужен один инструмент: Spark. Но 90% админов используют его примерно на уровне:
О, тут есть график!
Давайте поговорим о том, где на самом деле лежит правда.

Overview - красивая игрушка для новичков​

Когда вы открываете репорт spark, на первой вкладке Overview есть красивые проценты: Entity Tick, Block Tick, Plugins, Misc. Новичок смотрит на это и делает вывод:
Ага, Entities много. Нужно их уменьшить.
Проблема в том, что Overview - это агрегированная статистика. Они ничего не говорит о причине. Это примерно как увидеть в top: java 120% CPU. Спасибо, капитан.

Call Tree - место, где начинается настоящая диагностика​

Если вы хотите понять понять почему происходит нагрузка - открывайте Call Tree. Это буквально дерево вызовов JVM. Каждая строка показывает: кто вызвал функцию, сколько времени она заняла.
Пример (упрощённо):
CallTree:
MinecraftServer.tickServer
 └─ ServerLevel.tick
     └─ Level.tickEntities
         └─ Villager.tick
             └─ Brain.tick
                 └─ BehaviorGate.tryStart
И вот здесь начинается интересное. Потому что вы можете увидеть точную цепочку, где тратится CPU.

Entity Tick и настоящая причина лагов​

В Overview вы увидите: Entity Tick 40%. Новичок думает:
Мобов слишком много.
Но открываем дерево вызовов, и внезапно видим:
CallTree:
Level.tickEntities
 └─ Villager.tick
     └─ Brain.tick
         └─ AcquirePoi
Что это значит? Жители постоянно ищут рабочие блоки. Если игрок сделал ферму с 200 жителями - их AI начинает: поиск точек интереса, перепланирование пути, обновление памяти. И это происходит каждый тик. CPU начинает гореть.

Другой частый убийца - Pathfinding​

Call Tree может выглядеть так:
CallTree:
Mob.tick
 └─ PathfinderMob.tick
     └─ PathNavigation.moveTo
         └─ PathFinder.findPath
Это означает: мобы постоянно пересчитывают путь. Обычно виноваты: фермы с мобами, огромные загоны, сложная геометрия блоков. Pathfidning это по сути A* алгоритм. И он дорогой по CPU.

Hopper Storm: скрытый ад серверов​

Еще один частый сценарий. В Call Tree вы видите:
CallTree:
HopperBlockEntity.tick
 └─ tryMoveItems
Если таких записей тысячи, поздравляю, у вас ферма из воронок. Воронка проверяет: инвентарь сверху, инвентарь снизу, инвентарь сбоку. И делает это 20 раз в секунду. 5000 воронок = 100 000 операций в секунду. Никакой Ryzen это не любит.

Скрытый враг: IO Wait​

Иногда Call Tree выглядит странно. Вы видите:
CallTree:
MinecraftServer.tickServer
 └─ RegionFile.write
Или
CallTree:
ChunkStorage.write
Но использование CPU при этом низкое. Это классический слушай IO Wait. Что происходит: сервер пытается записать чанк на диск, но диск не отвечает быстро. Основной поток блокируется, и тик стоит.

Симптомы IO проблем
На Linux смотрим top или лучше htop и ищем показатель wa это IO Wait. Если там 10%+, то диск начинает тормозить сервер.

Частые причины
  1. Медленный VPS SSD
  2. Перегруженный NVMe у хостинга
  3. World AutoSave
  4. Огромные Region файлы
Minecraft пишет тонны мелких операций. Если диск имеет высокую задержку - тик зависает.

Async Profiler: уровень хардкор​

Если вы хотите реально понимать сервер, используйте Spark так:
/spark profiler start --engine async
Это включает async-profiler. Почему это важно? Обычный Profiler JVM видит только Java Stack. Async Profiler видит: Java, C++, Kernel, System Calls. То есть вы начинаете видеть такие вещи: epoll_wait, pthread_cond_wait, write, futex. И внезапно становится понятно: сервер не грузит CPU, он ждёт систему.

Почему это важно​

Потому что иногда проблема выглядит так: 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=8M
На Java 8 это имело смысл. Но на Java 21 ситуация изменилась. JVM уже сама умеет настраивать G1 лучше, чем человек с Reddit. Когда вы добавляете десятки старых флагов, JVM: теряет адаптивность, работает с устаревшими параметрами, может ухудшать задержки GC. Ирония в том, что многие сервера сейчас запускаются примерно так: java 21 + флаги 2017 года

Минималистичный современный запуск​

Сегодня нормальный запуск выглядит примерно так:
Bash:
java \
-Xms10G \
-Xmx10G \
-XX:+UseZGC \
-jar paper.jar
Всё. Никаких 40 флагов. JVM 21 уже содержит: адаптивный размер кучи, улучшенное распределение областей, улучшенную эвристику JIT. Иногда меньше - реально лучше.

ZGC: почему паузы стали микроскопическими​

Главная причина отказаться от старого подхода - это новые 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 - это база. Но сейчас существуют ядра, которые делают более агрессивную оптимизацию тиков. Самые известные:
  1. Pufferfish
  2. Purpur
И одна из самых интересных систем внутри них - это: Dynamic Activation Buffer, или просто DAB.

Dynamic Activation Buffer: почему это умнее, чем "удалить мобов"​

Классическая оптимизация завязана на entity-activation-range, то есть мобы далеко от игрока перестают тикаться. Но это очень грубый механизм. Он ломает: фермы, искусственный интеллект, поведение мобов. DAB работает иначе. Он делает динамический бюджет тиков. Упрощённо: сервер смотрит сколько времени осталось до 50 ms, и если времени мало, он адаптивно уменьшает активность сущностей. Не всех. А только тех, которые: далеко, менее важны, не взаимодействуют с игроками. В результате: важные мобы продолжают тикаться, второстепенные замедляются. И сервер держит TPS стабильно. Это гораздо ближе к тому, как реальные игровые движки управляют нагрузкой.

Маленькая правда о "плохих плагинах"​

Никакая оптимизация ядра не спасёт сервер, если плагин делает O(n2) обходы, или синхронные SQL запросы в основном тике. Call Tree в spark иногда выглядит так:
CallTree:
Plugin.tick
 └─ Database.query
     └─ mysql socket wait
И весь сервер стоит. Это не проблема Minecraft. Это проблема кода плагина.

Золотые правила админа сервера​

После 10 лет возни с JVM и Minecraft можно сформулировать несколько простых правил.
  1. TPS убивает не RAM, а задержки одного потока.
  2. GC должен быть простым, сегодня это ZGC или Shenandoah, а не археология из 2017 года.
  3. Профилирование важнее конфигов, всегда сначала профайлер spark и дерево вызовов, а уже потом настройки.
  4. Мир - главный источник нагрузки, TPS чаще всего убивают фермы мобов, поиск путей, воронки, массивная загрузка чанков, а не paper.yml.

Финальная мысль​

Оптимизация Minecraft сервера это не поиск магического числа в конфиге. Это системная задача, она включает в себя:
  1. Понимание JVM
  2. Понимание Задержки CPU
  3. Анализ Spark профайлера
  4. Анализ Ввода/Вывода
  5. Анализ Игровой логики
Если вы просто копируете чужие конфиги - вы угадываете. Если вы читаете метрики - вы управляете системой. А серверы, как и любые сложные системы, всегда лучше работают под управлением инженеров, а не коллекционеров YAML-файлов.
 
ВерхНиз