42f48fea43
Build Delta / Build paperclip jar (push) Successful in 7m3s
Добавлен -XX:MaxHeapFreeRatio=30 -XX:MinHeapFreeRatio=10 в start.sh на проде
и зафиксирован в README с замерами, потому что флаги JVM не переносятся
копированием конфигов — при переезде они теряются молча.
Замер, мир 18 МБ, 0 игроков, 100 с простоя:
коммит живые RSS
без флагов 630 МБ 278 МБ 0.99 ГБ
с флагами 389 МБ 274 МБ 0.69 ГБ
Минус 300 МБ RSS без единого ручного GC.
Причина была не в отсутствии Full GC: jcmd GC.run отрабатывает, живые падают
289 -> 248 МБ, но коммит остаётся на 725 МБ. G1 сжимает кучу только когда
свободно выше MaxHeapFreeRatio, а он по умолчанию 70. При 630 МБ коммита
свободно было 56% — ниже порога, и 350 МБ держались вечно.
Паузы Mixed (то, что ест кадр в рантайме) не ухудшились: median 11.0 -> 9.8,
p95 28.3 -> 28.1, max 38.1 -> 28.7 мс. Concurrent-циклов стало больше
(11 -> 18), общий p95 по всем паузам в одном прогоне вырос 126 -> 270 мс —
это замер без игроков, под нагрузкой флаг ещё предстоит перемерить.
DisableExplicitGC оставлен намеренно: он делает System.gc() no-op, и именно
поэтому освобождение сделано флагом, а не вызовом GC. README теперь
описывает профиль как 15-25 игроков с пиком 34, а не 30-40.
122 lines
8.0 KiB
Markdown
122 lines
8.0 KiB
Markdown
# 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. |