Spark профайлер: как найти причину лагов Minecraft сервера в 2026
Сервер тормозит, TPS пляшет в районе 14, в чате жалобы на "лаги", а ты сидишь и не понимаешь, кто именно жрёт тик. Раньше открывал /timings paste и через минуту знал виновника. Сегодня Timings внутри Paper фактически мёртв (отключён по умолчанию с 1.20.5, выпилен в 1.21+), а Aikar's Timings v2 как отдельный продукт давно не развивается. На замену пришёл Spark от lucko, и за последние два года он стал стандартом отрасли: его рекомендует команда PaperMC, его упоминают в багрепортах Mojang, его поддерживают авторы Purpur, Folia, Fabric и большинства крупных модпаков.
Эта статья показывает, как поставить Spark в 2026 году, как снять полезный профиль с продакшена, как читать flame-graph, не превращаясь в шамана, и как из дерева вызовов вытащить конкретного виновника падения TPS, будь то плагин, чанк или сборка мусора.
Что такое Spark и почему он вытеснил Timings
Spark, это сэмплирующий профайлер для JVM, заточенный под Minecraft. Он не инструментирует код, как старый Timings, а с фиксированной частотой делает снимки стека всех потоков сервера. Из этих снимков строится дерево вызовов и flame-graph, по которому видно, где сервер реально проводит CPU-время.
Ключевое отличие от Timings: Spark показывает не "сколько тиков заняла обработка событий плагина X", а "какие именно методы и в каком стеке грелись на CPU". Это даёт честную картину, включая то, что Timings никогда не видел: внутренние методы Mojang, тяжёлые операции внутри плагинов, лямбды, нативный код, GC-паузы.
Почему Timings ушёл со сцены, понятно. Он был встроен в Paper, тащил накладные расходы, замерял только то, что специально обернули таймером, искажал картину при асинхронном коде и плохо ловил GC. С Paper 1.20.5 команда отключила Timings по умолчанию, в 1.21 удалила полностью. Spark при этом работает на любой версии от 1.8 до 1.21.x, на Spigot, Paper, Folia, Fabric, Forge, NeoForge, Velocity и BungeeCord.
Автор Spark, lucko, разработчик LuckPerms. Spark разрабатывается открыто на github.com/lucko/spark, официальный сайт spark.lucko.me, плагин раздаётся через Hangar (hangar.papermc.io/lucko/spark) и Modrinth (modrinth.com/plugin/spark). На апрель 2026 актуальна ветка 1.10.x, поддерживается Java 21 и серверы вплоть до 1.21.5.
Установка на разные платформы
Spark поставляется как один универсальный JAR с автодетектом платформы, плюс отдельные сборки для Fabric и Forge. Скачивай с spark.lucko.me/download или с Modrinth, не с reupload-сайтов.
Spigot, Paper, Purpur, Folia. Кидаешь spark-1.10.x-bukkit.jar в plugins/ и перезапускаешь сервер. После старта команда /spark доступна по праву spark. По умолчанию доступ только у operator-ов, для не-OP игроков выдай право через LuckPerms: lp user <name> permission set spark true.
Velocity. Для прокси нужен spark-1.10.x-velocity.jar, кладёшь в plugins/ Velocity-прокси. На прокси Spark особенно полезен, чтобы ловить лаги в обработке Plugin Messages, при подключении игроков, в работе LiteBans и подобных тяжёлых плагинов.
BungeeCord и Waterfall. Есть отдельный spark-1.10.x-bungeecord.jar. Команды те же, флаги те же. Имей в виду, Bungee/Waterfall в 2026 уже legacy, миграция на Velocity рекомендована.
Fabric. Quilt и Fabric используют spark-1.10.x-fabric.jar, кладёшь в mods/. Зависит от Fabric API. Если играешь на сервере, ставь только серверную версию мода, для клиента есть отдельная сборка spark-fabric-client.
Forge и NeoForge. Forge версии 1.20.1 и старше: spark-1.10.x-forge.jar в mods/. Для NeoForge 1.20.4+ есть отдельный JAR spark-neoforge. Команды те же, доступ через /spark от имени оператора, права через FTB Ranks или OpenPartiesAndClaims.
Sponge. Поддерживается через spark-1.10.x-sponge.jar. На SpongeForge ставится в mods/, на SpongeVanilla в plugins/.
После установки проверь работу командой /spark, она выведет справку. Если выдаёт "unknown command", смотри в latest.log: плагин может ругаться на старый Java (нужен 17+, рекомендован 21).
Базовые команды: /spark profiler, /spark tps, /spark health
Spark, это набор подкоманд под общим /spark. Разберёмся с теми, что используются 95% времени.
/spark tps
Показывает текущий TPS и MSPT (миллисекунды на тик), разбитый по интервалам:
TPS from last 5s, 10s, 1m, 5m, 15m:
*14.2, *16.8, 19.4, 19.8, 19.9
Tick durations (min/med/95%ile/max ms) from last 10s, 1m:
3.2 / 12.4 / 48.1 / 220.5
Звёздочка перед числом, это значение ниже целевого. 95-й процентиль миллисекунд на тик, самая полезная цифра: показывает не средний MSPT, а тот, что был хуже, чем у 95% тиков. Если 95%ile стабильно выше 50ms, у тебя проблема, даже когда средний TPS красивый.
/spark profiler
Главная команда. Запускает сэмплирующий профайлер, по умолчанию на основном потоке сервера. Без аргументов работает до тех пор, пока не остановишь руками через /spark profiler stop.
/spark profiler start
... ждём 60-300 секунд во время лагов ...
/spark profiler stop
По остановке Spark загружает результат на bytebin (свой публичный pastebin для бинарных дампов) и кидает в чат ссылку вида https://spark.lucko.me/abc123def. Открываешь её в браузере и работаешь с интерактивным viewer-ом.
Полезные флаги:
--timeout 120, авто-остановка через 120 секунд. Удобно, когда лагает регулярно.--thread *, профилировать все потоки JVM, а не только Server Thread. Нужно при подозрении на async-плагины, GC и Netty.--only-ticks-over 100, сохранять стеки только тех тиков, что заняли больше 100ms. Голден-режим для редких фризов посреди нормального TPS.--interval 10, семплинг с интервалом 10ms (по умолчанию 4ms). Снижает нагрузку на длинных профилях.
/spark health
Свежая команда, заменила старый /spark tickmonitor. Быстрый обзор JVM:
Server Health Report:
TPS: 18.4 (last 5s)
CPU: 64% (process), 82% (system)
Memory: 8.4G / 12G heap
GC: G1 Young 12 collections, 340ms total
Disk: /world 240G free of 500G
Если system CPU высокий, а process CPU низкий, на машине кто-то ещё ест CPU, типичный кейс шаред-хостинга.
/spark heapsummary и /spark heapdump
/spark heapsummary, лёгкий снимок: сколько объектов каждого класса в куче и сколько они весят. Хватает, чтобы поймать утечку памяти у плагина: видишь org.bukkit.craftbukkit.v1_21_R1.entity.CraftItem в количестве 480000, и понимаешь, кто-то не очищает дропы.
/spark heapdump, полноценный hprof-дамп для VisualVM или Eclipse MAT. Использовать только когда heapsummary не дал ответа: дамп пишется на диск, может занимать гигабайты, и на время записи сервер встаёт колом.
/spark gc
Статистика сборщика мусора с момента старта. Полезно сравнить, сколько времени JVM провела в GC-паузах против полезной работы. Цифра выше 5%, плохая новость, выше 15%, пора чинить флаги Java или искать утечку.
Чтение flame-graph: Self time vs Total time
Graph viewer на spark.lucko.me, перевёрнутый flame-graph: корень дерева сверху, листья снизу. Каждый прямоугольник, метод, ширина пропорциональна времени, потраченному в этом методе. Чем шире, тем горячее.
Total time включает время, проведённое в самом методе и во всех его вызовах. У корня дерева Total всегда 100%. Полезен, чтобы выбрать ветку, которая целиком тянет CPU.
Self time считает только время непосредственно в методе, без потомков. Сужается на самые низкие "горячие" листья. Именно по Self time ловят кривой код.
Практическое правило: смотришь Total, чтобы выбрать ветку ("60% времени уходит в ChunkMap.tick"), переключаешься на Self time и идёшь вниз по ветке, ища, где Self становится максимальным. Этот лист, конкретная функция, в которой проблема.
Spark подкрашивает прямоугольники по типу кода: Mojang/NMS один цвет, плагины другой, JVM третий. Включи в настройках viewer-а "Colour by source", и сразу увидишь, что 40% тика жрёт один конкретный плагин на красном фоне. Ctrl+F открывает поиск по имени метода, можно искать по пакету (com.discordsrv), классу (AsyncCatcher) или имени метода. Кнопка "Sources" группирует всё дерево по источнику, сразу видно top-3 виновника.
Типичные виновники лагов и как их видно в Spark
Загрузка и генерация чанков. В дереве это ServerLevel.tick -> ChunkMap.tick -> ChunkGenerator.generate. Если эта ветка съедает 30%+ Total time, виноваты либо игроки, исследующие новые территории, либо плагин, который грузит чанки сам (динмап, AntiAFK телепорты, рекламные плагины с автотп). Решение: предгенерация мира через Chunky, ограничение view-distance до 8-10, отключение принудительной загрузки чанков в сторонних плагинах.
Тик-лист сущностей. Ветка EntityTickList.forEach -> Mob.tickAi -> PathFinder.findPath. Если поиск пути жрёт 20%+, у тебя где-то застрявшие мобы (типичный кейс, забитый загон с коровами) или жители со сломанным AI. Лечится /spark profiler --only-ticks-over 100, потом kill @e[type=cow,distance=..200] для конкретных загонов или включением Lobotomize villagers в Purpur.
Редстоун. ServerLevel.tickBlock -> RedstoneWireBlock.updateState. Эта ветка любит вспыхивать у больших технических серверов. Решение: redstone-implementation: ALTERNATE_CURRENT в paper-world-defaults.yml, замена тактовых генераторов на наблюдателей или сравниватели.
Сборщик мусора. GC видно как широкие прямоугольники в потоках G1 Young Gen, G1 Concurrent, ZGC Concurrent. Если профиль с --thread * показывает, что GC занимает 10%+ wall-clock, флаги Java неправильные или у тебя просто мало RAM. Перепроверь -Xms равен -Xmx, попробуй G1 с aikar-флагами или ZGC на Java 21.
Плагин-плохиш. Классика: вешаешь --thread * и видишь, что один плагин в потоке pool-7-thread-1 стабильно жрёт CPU и делает Socket.connect, JDBC.executeQuery или URL.openStream. Это и есть тот самый "асинхронный" плагин, который ходит на внешний API на каждый event. Ищи имя плагина в стеке, отключай или ругай автора.
Авто-сейв. Каждые 5-10 минут в профиле всплывает большой Self time у ChunkSerializer.write и RegionFile.write. Это нормально, но если на авто-сейве TPS падает с 20 до 10, диск медленный (HDD вместо NVMe), либо мир слишком большой и пора paper trim или chunky trim.
Как поделиться отчётом
Как только профайлер останавливается, в чате/консоли появляется ссылка на bytebin типа https://spark.lucko.me/abc123def. По этой ссылке любой человек видит интерактивный viewer.
Что стоит знать:
- Ссылки на bytebin живут долго, но не вечно. Если профиль нужен надолго, скачай
.sparkprofileфайл из viewer-а кнопкой "Download". - Профили публичные, по ссылке открываются без пароля. В дамп попадают имена пакетов, классов и методов, иногда имена игроков (через лямбды), иногда конфиденциальные пути файлов.
- В viewer-е есть кнопка "Anonymize". Включает замаскированные имена игроков и обезличенные пути.
Для поддержки от авторов плагинов: bytebin-ссылка, это то, что у тебя попросят на Discord-сервере PaperMC, EssentialsX или любого крупного плагина. Не надо постить скриншоты, не надо выдёргивать строки из логов.
Cheatsheet команд Spark
| Команда | Что делает | Когда использовать |
|---|---|---|
/spark tps | Текущий TPS + MSPT по интервалам | Быстрая проверка, есть ли проблема |
/spark profiler start | Запуск профайлера | Диагностика лагов на основном потоке |
/spark profiler stop | Остановка + загрузка отчёта | После сбора достаточного семпла |
/spark profiler --timeout 120 | Авто-стоп через 120 сек | Когда не хочется возвращаться вручную |
/spark profiler --thread * | Все потоки JVM | Подозрение на async-плагины, GC, Netty |
/spark profiler --only-ticks-over 100 | Только тики дольше 100мс | Редкие фризы при нормальном TPS |
/spark profiler --interval 10 | Семплинг с интервалом 10мс | Снизить нагрузку на длинных профилях |
/spark profiler info | Статус текущего профилирования | Проверить, идёт ли запись |
/spark profiler cancel | Отмена без отчёта | Передумал собирать |
/spark health | Здоровье JVM: CPU, RAM, GC, диск | Первый взгляд при жалобах на лаги |
/spark heapsummary | Лёгкий снимок объектов в куче | Поиск утечек памяти |
/spark heapdump | Полный hprof-дамп на диск | Глубокий разбор утечек в VisualVM/MAT |
/spark gc | Статистика сборщика мусора | Диагностика GC-проблем |
/spark ping | Пинг игроков с сервера | Сетевая диагностика |
/spark activity | Лог активности плагинов | Что и кем было запущено недавно |
Продвинутые опции
Сравнение профилей. В viewer-е есть кнопка "Compare", даёт diff между двумя профилями. Полезно после оптимизации: снимаешь "до" и "после", смотришь, какая ветка действительно ушла. Иногда видно, что починил одно, но утяжелил другое: отключил динмап, но Essentials стал чаще писать на диск.
Профилирование Folia. Folia, многопоточный форк Paper, имеет несколько Region Threads. Spark корректно ловит каждый, в viewer-е они показаны отдельными деревьями. На Folia особенно полезен --only-ticks-over, чтобы поймать, какой регион отстаёт.
Конфиг spark.yml. В plugins/spark/config.json можно настроить URL bytebin (для своего инстанса), отключить публичные ссылки (viewer-url-only-private: true), включить автоматический сбор профиля при падении TPS ниже порога:
{
"profiler": {
"auto": {
"enabled": true,
"trigger-tps": 10.0,
"duration": 90
}
}
}
С такой настройкой Spark сам поймает следующий фриз, не нужно сидеть и ждать.
REST API. Spark публикует REST API через bytebin, можно автоматизировать сбор и хранение профилей. У lucko есть пример скрипта в репозитории, удобно для крупных сетей.
Сравнение с Timings и Aikar's Timings v2
| Параметр | Timings (Paper) | Timings v2 (Aikar) | Spark |
|---|---|---|---|
| Статус в 2026 | Удалён в Paper 1.21+ | Не развивается | Активно развивается |
| Метод | Инструментирование | Инструментирование | Сэмплирование |
| Ловит NMS код | Ограниченно | Ограниченно | Полностью |
| Async потоки | Нет | Частично | Полностью |
| Ловит GC-паузы | Нет | Нет | Да |
| Накладные расходы | Средние | Средние | Низкие (1-2%) |
| Поддержка Folia | Нет | Нет | Полная |
| Fabric/Forge | Нет | Нет | Полная |
| Поделиться отчётом | timings.aikar.co | timings.aikar.co | spark.lucko.me |
| Сравнение профилей | Нет | Нет | Да |
| Heap-анализ | Нет | Нет | Да |
Практический вывод. Если у тебя ещё стоит Timings (на Paper 1.20.4 или ниже), переходи на Spark прямо сейчас. Параллельно держать Timings нет смысла, накладные расходы суммируются. Aikar's Timings v2 как отдельный продукт можно забыть, его автор сам перешёл на Spark и рекомендует его в гайдах по флагам Java.
FAQ
Spark тормозит сервер?
Сэмплирующий профайлер по умолчанию шлёт ~1% накладных расходов CPU на интервале 4ms. Это меньше, чем стоил Timings в активном режиме. На профиле длиннее 5 минут разница в TPS не выходит за статистическую погрешность.
Можно ли держать Spark постоянно?
Да, и многие так делают. Сам по себе плагин ничего не профилирует, пока не запустишь команду. Накладные расходы простаивающего Spark близки к нулю. /spark health тоже работает в фоне без записи стеков.
Что делать, если bytebin недоступен?
Можно скачать профиль локально кнопкой --save-to-file или загрузить на свой инстанс bytebin (исходники открыты на GitHub lucko). Локальный viewer тоже есть: открываешь скачанный .sparkprofile файл прямо в браузере на spark.lucko.me, он не загружается на сервер.
Spark покажет DDoS?
Нет. Spark, профайлер CPU и памяти Java, он смотрит, что делает сам сервер. Внешнюю сетевую нагрузку (UDP-флуд, бот-атаки на login) он не видит. Для защиты от DDoS нужна сетевая фильтрация перед сервером, как у MineGuard, Spark лишь покажет, что в твоих лагах виноват не плагин, а внешний фактор.
Какой профиль слать автору плагина в баг-репорте?
Минимум 60 секунд работы во время реальной нагрузки, флаги --thread *, плюс /spark health снапшот. Если проблема редкая, добавь --only-ticks-over 100. Опиши версию сервера, версию плагина и количество онлайна на момент снимка.
Подходит ли Spark для клиента?
Да, есть отдельные сборки spark-fabric-client и spark-forge-client. Полезно для модпак-разработчиков и стримеров, чтобы понять, какой мод дёргает FPS. Команды на клиенте те же, вызываются через keybind или чат.
Если после получасового изучения flame-graph ты упёрся в стену "всё горит, и непонятно", это нормально, профилирование, навык. Снимай профили регулярно, сравнивай до и после изменений, копи насмотренность. Через десяток отчётов начнёшь узнавать ChunkMap.tick и SpongeRedstone издалека. Главное помни: Spark покажет внутренние тормоза, но если лаги от внешней нагрузки (бот-атака, UDP-флуд, синтетический пинг), профайлер будет молчать, потому что виноват не сервер, а сеть, и тут нужна уже сетевая защита уровня MineGuard, а не дальнейшее ковыряние в коде.
Proteja Seu Servidor de Ataques DDoS
Proteção gratuita com configuração em 5 minutos. 1 TB de tráfego incluso.
Experimentar GrátisArtigos Relacionados
Servidor Minecraft SMP em 2026 - Guia de Criação e Configuração
Guia completo de SMP: escolha de core (Paper, Purpur, Folia, Fabric), flags da JVM, tuning do server.properties e paper.yml, pré-geração, plugins de proteção e economia, anti-cheat Grim vs Vulcan, anti-bot, voice chat, backups 3-2-1, monetização sem pay-to-win e proteção DDoS.
Бесплатная защита Minecraft сервера от DDoS: как это работает
Полноценная DDoS-защита для Minecraft не обязана стоить дорого. Рассказываем про бесплатный тариф MineGuard: что входит, кому подходит и когда стоит переходить на платный план.
BetonQuest: настройка квестов на Minecraft сервере (гайд 2026)
Полный гайд по BetonQuest 2.x: установка, формат пакетов, диалоги, objectives, conditions, events, журнал, миграция с 1.x и узкие места по TPS.