# ZernMC configs Тюнинг под профиль: **4 vCPU / 8 GB RAM, 15–25 игроков постоянно, пик 34**, боевой сервер с плагином, который спавнит много `Display`/`Marker` сущностей и частиц (BlackKnife как референс). Все файлы **парциальные** — Paper/Spigot дополняет недостающие ключи дефолтами, поэтому их можно копировать поверх существующих конфигов. ## Куда класть | Файл | Путь на сервере | |---|---| | `spigot.yml` | `<сервер>/spigot.yml` | | `paper-world.yml` | `<сервер>/<мир>/paper-world.yml` — **у каждого мира свой** | | `paper-global.yml` | `<сервер>/config/paper-global.yml` | | `server.properties.patch` | ключи из него в `<сервер>/server.properties` | ## Что где меняем и зачем ### `spigot.yml` - `view-distance 8 / simulation-distance 5` — на 4 ядрах это самый ощутимый рычаг: симуляция шириной 10 стоит в разы дороже 5. - `entity-tracking-range.display 128 → 48` — **главный фикс**. Display, ItemDisplay, TextDisplay, Marker шлются игрокам пачками; при спаме боеспособностей 128 это десятки пакетов на тик. - `misc 96 → 48`, `other 64 → 32`, `animals/monsters 96 → 64`, `players 128 → 96` — то же, но по остальным типам. - `entity-activation-range` — сужаем радиусы, в которых сущности вообще тикают; `tick-inactive-villagers: false` — самый частый выигрыш. - `ticks-per.hopper-check 1 → 8` — хопперы по умолчанию проверяются каждый тик, 8 экономит заметно и не ломает фермы. - `merge-radius.item 0.5 → 2.5` — меньше сущностей-дропа на земле. - `item-despawn-rate 6000 → 3000`, `arrow-despawn-rate 1200 → 300`. - `mob-spawn-range 8 → 6`, `max-tnt-per-tick 100 → 30`. ### `paper-world.yml` - `misc.redstone-implementation: ALTERNATE_CURRENT` — быстрее распространение редстоуна. **Ломает 0-tick и двери-контры**, предупредить игроков перед включением. - `tick-rates` — рост травы, обновление контейнеров, спавнеры в 3 тика. - `collisions.max-entity-collisions 8 → 5`. - `environment.disable-thunder`, `optimize-explosions`, `max-block-ticks`/`max-fluid-ticks` пополам. - `hopper.disable-move-event: true` — **ломает плагины, слушающие `InventoryMoveItemEvent`** (авто-сортировки, economy-логики). - `entities.spawning.spawn-limits` — потолок мобов на чанк. ### `paper-global.yml` - **`chunk-system.worker-threads: 2`** — самый недооценённый рычаг. `auto` (`-1`) на 4 ядрах даёт **1 воркер**, и генерация чанков идёт последовательно: Moonrise делит `availableProcessors` пополам, а на результате 2 опускается до 1, оставляя место главному треду. Замерено: холодный старт **38.5 → 24.9 с**, тёплый **16.4 → 12.2 с**. Значение 3 — только с профилем, главному треду на 4 ядрах нужно дышать. - `chunk-system.io-threads: 2`, `gen-parallelism: true`. - `chunk-loading.advanced.player-max-concurrent-chunk-loads/generates` — защита от флуда генерацией при скоростном облёте. **При ускорении генерации этот потолок надо поднимать**, иначе движер быстрее, а ограничитель остался прежним. ## Что НЕ трогаем - Moonrise (чанковая система) — уже многопоточный, отдельный патч не нужен. - `wake-up-inactive.*` — баланс, не перф. ## JVM-флаги кучи (живут в `start.sh`, не в конфигах) Эти флаги **не переносятся копированием конфигов** — они в скрипте запуска. Потеряются при переезде, поэтому дублируются здесь. ### `-XX:MaxHeapFreeRatio=30 -XX:MinHeapFreeRatio=10` Замер на сервере с миром 18 МБ, 0 игроков, после 100 с простоя: | | коммит | живые | RSS | |---|---|---|---| | без флагов | 630 МБ | 278 МБ | **0.99 ГБ** | | с флагами | 389 МБ | 274 МБ | **0.69 ГБ** | Минус 300 МБ RSS на пустом сервере, без единого вызова GC вручную. Почему работает. `G1PeriodicGC` гоняет Mixed/Remark каждые 15 с, но кучу почти **никогда не сжимает**: G1 сжимает только когда доля свободной памяти выше `MaxHeapFreeRatio`, а он по умолчанию **70**. При 630 МБ коммита и 278 МБ живых свободно было 56% — ниже порога, поэтому 350 МБ коммита держались вечно и в RSS, и в физической памяти. Отдельно проверено, что принудительный Full GC сам по себе **не помогает**: `jcmd GC.run` отработал, живые упали 289 → 248 МБ, а коммит остался на 725 МБ. То есть дело не в отсутствии Full GC, а именно в пороге. Паузы при этом не ухудшились — то, что реально ест кадр в рантайме: | Pause Young (Mixed) | без флагов | с флагами | |---|---|---| | median | 11.0 мс | 9.8 мс | | p95 | 28.3 мс | 28.1 мс | | max | 38.1 мс | 28.7 мс | Оговорка: concurrent-циклов стало больше (11 → 18), потому что куча меньше и G1 переполняет её чаще. Каждый такой цикл начинается с STW-паузы, и общий p95 по всем паузам в одном прогоне вырос (126 → 270 мс). Это замер на сервере без игроков, один прогон — **под нагрузкой это надо перемерить**, прежде чем считать флаг безопасным. ### `-XX:+DisableExplicitGC` Оставлен намеренно: `System.gc()` отключён, чтобы ни плагин, ни сторонний код не могли вызвать stop-the-world сборку в неподходящий момент. Именно поэтому освобождение кучи сделано флагом, а не вызовом GC. ### Что будет, когда мир вырастет до 2–4 ГБ Флаг этого не ломает. Он разрешает сжимать кучу, когда свободно больше 30%, и не мешает расти: при `-Xmx4G` G1 расширится сам, как только живых данных станет больше. Экономия в 300 МБ в основном на простое и при малом мире. ## Порядок применения 1. Остановить сервер. 2. Скопировать файлы. 3. `paper-world.yml` положить в **каждый** мир: `world/`, `world_nether/`, `world_the_end/`. 4. Флаги кучи из раздела выше — в `start.sh`, вручную. 5. Старт → в логе не должно быть `Error occurred while loading` по этим файлам. 6. Проверить: `/paper entity` (tracking ranges), `spark` для TPS/MSPT.