Server Debugger

 Server Debugger

El_Neuman

Мод для владельцев серверов. Отвечает на вопрос "почему мой сервер лагает" - и, если виноват какой-то мод, называет его по имени. Отдельный мод, ничего за собой не тянет. Ставится только на сервер, игрокам скачивать не нужно.

Писался в расчёте на то, что ты не программист. Команды ниже объяснены простыми словами: что делает, зачем, и что покажет.


Общая информация - что вообще происходит, когда "сервер лагает"

 

Сервер раз в доли секунды делает "тик" - обсчитывает мир: мобов, костры, температуру, всё сразу. Если один тик занимает не 0.05 секунды, а, скажем, 5 секунд - для игроков это фриз: мобы замирают, блоки не ставятся, всех "телепортит".

Причин у долгого тика немного, и они разные по лечению. Этот мод умеет отличать их друг от друга и показывать, какая именно у тебя.

Три вещи, которые надо знать, чтобы понимать вывод мода:

  • Мусор и его уборка (GC). Игра и моды постоянно создают в памяти временные объекты. Когда их накапливается много, система устраивает "уборку мусора" (GC - garbage collection): замирает, проходит по всей памяти и выкидывает ненужное. Пока идёт уборка - сервер стоит. Обычно это доли секунды и незаметно. Но если памяти скопились гигабайты, одна уборка может занять секунды - вот и фриз.
  • Утечка памяти. Уборка выкидывает только то, что больше никому не нужно. Если какой-то мод по ошибке продолжает "держать" уже мёртвых мобов (не отпускает ссылку на них) - уборка их выкинуть не может. Они копятся. Память растёт, уборки становятся всё длиннее, сервер лагает всё сильнее. Это и есть утечка.
  • Горячий код. Иногда фриз не от памяти, а от того, что какой-то мод просто делает слишком много работы каждый тик (например, зря пересчитывает тысячи блоков). Память не растёт - код честно считает, но долго. Лечится не уборкой памяти, а поиском самого мода.

Чем Server Debugger отличается от MemLeakInspector?

MemLeakInspector - это специализированный инструмент для исследования памяти. Он показывает, какие объекты находятся в памяти, позволяет анализировать их состояние и сравнивать снимки памяти между собой. Однако он не определяет автоматически причину проблемы - интерпретировать результаты и искать виновника приходится самостоятельно.

Server Debugger - это комплексный инструмент диагностики сервера. Он анализирует зависания main-потока, лаги, паузы GC, проблемы с диском и утечки памяти. При обнаружении утечки он сразу пытается определить мод-виновник, что значительно ускоряет поиск проблемы. При этом он не предоставляет глубокий анализ объектов в памяти, временные снимки или подробный дашборд использования памяти.

Иными словами, Server Debugger отвечает на вопрос "какой мод вызывает проблему?", а MemLeakInspector - "какие объекты находятся в памяти и как меняются со временем". Эти инструменты не заменяют друг друга, а отлично работают вместе.


Что мод умеет, а что нет

Ловит уверенно и сам

  • Утечки памяти. Когда какой-то мод по ошибке копит в памяти мёртвые энтити (мобов) и не отпускает - память растёт, сервер лагает всё сильнее. Мод находит это и называет виновника по имени (команда whodunit). 
  • Горячий код - какой мод. Если фриз от того, что мод долго считает каждый тик, команда ticks называет топ модов по нагрузке на сервер - без гадания и без ручной настройки. Раньше для этого нужно было вписывать подозреваемых вручную; теперь мод сужает круг сам.
  • Кто спавнит сущности и что копится. Если растёт число мобов/снарядов, а leak упирается в "ваниль / движок" - команда spawns показывает, какой мод плодит сущности и что именно накапливается (спавнится быстрее, чем деспавнится). Это ловит случай, когда сущности не "утекли", а их просто слишком много спавнят.
  • Понять, от чего вообще лаг. На каждый фриз мод говорит, куда ушло время: на уборку мусора, на слишком долгий код, или сервер просто ждал (диск, железо). Направление укажет всегда - не будешь гадать и копать не там.
  • Кто вручную дёргает уборку мусора. Иногда мод сам приказывает "убрать мусор сейчас", и на большой памяти это фриз. Команда /sdebug gccallers показывает, какой мод это делает.
  • Плохие настройки уборки мусора. Команда /sdebug env покажет, включён ли быстрый режим уборки, и если нет - это можно исправить (пример вывода и как чинить - ниже).

Помогает, но не назовёт виновника мгновенно

  • Точные цифры по "тяжёлому коду". ticks сужает круг до 2-3 модов, но показывает частоту тиков, а не время. Мод может тикать часто, но быстро. Чтобы узнать, кто именно ест время, есть profile - он замеряет время по кускам кода, но смотрит только на моды, указанные в настройке. То есть: ticks назовёт подозреваемых сам, а profile подтвердит точными цифрами, если впишешь их в настройку.

Не умеет вообще

  • Лаги из-за диска, сети или слабого железа хостинга. Мод скажет "причина не в коде модов" - но починить не сможет. Это к хостеру.
  • Лаги у игрока (низкий FPS, дёргается картинка). Мод чисто серверный, клиент он не видит вообще.
  • "Тяжело, но правильно". Если тех же тысяч блоков честно надо обсчитывать и в коде нет ошибки - мод покажет, что время уходит туда, но это уже не баг, а вопрос к тому, как мод устроен. Лечится не отладкой, а переделкой мода (или уменьшением нагрузки на сервере).

Одной фразой

Утечку памяти, горячий код и избыточный спавн - найдёт и назовёт мод сам. Всё остальное (диск, сеть, железо) - покажет верное направление, но дальше уже думать тебе.


Порядок действий - как дебажить по шагам

Команды вводятся в чат или консоль сервера, нужны права администратора. Не начинай с угадывания - иди по порядку, мод сам поведёт.

  1. Всегда начинай с /sdebug stalls - разбор последних фризов. Он сам напишет вердикт и укажет направление.
  2. Дальше смотри на вердикт:Вердикт "ПАУЗА GC" (память) -> /sdebug leak (есть ли утечка?), потом /sdebug whodunit (кто виноват?). Если whodunit упёрся в "ваниль / движок" - значит это не утечка, а избыточный спавн: включи /sdebug spawns on.
  3. Вердикт "горячий код" -> /sdebug ticks on, поиграй, потом /sdebug ticks (назовёт мод). Для точных цифр - profile + top.
  4. Вердикт "ожидание диска / lock" -> это железо/сеть хостинга, кодом не чинится.
  5. /sdebug env - общий осмотр в любой момент (в т.ч. проверить, включён ли быстрый режим уборки).

Всё пишется в файл Logs/serverdebugger-watchdog.txt - длинные отчёты смотри там. Трекеры (ticks on, spawns on) включай только когда дебажишь, потом off.


Команды

/sdebug stalls - разбор последних фризов (С НЕЁ НАЧИНАЮТ)

Когда вводить: первой, как только сервер лагает или лагал недавно. Это точка входа в любой разбор - она сама скажет, в какую сторону копать дальше. На свежезапущенном спокойном сервере покажет пусто (фризов ещё не было) - это нормально.

Мод ловит фризы сам и складывает их разбор. Эта команда показывает последние (по умолчанию 5). Каждый фриз - это блок, и последняя строка в нём - вердикт простым текстом, куда ушло время. Пример:

ServerDebugger: ЗАВИСАНИЕ 
  Длительность         : 5084 мс
  GC pause             : 5008 мс  (99%)
  ...
  ВЕРДИКТ : ПАУЗА GC. Сервер убирал мусор. Проверь на утечку: /sdebug leak

Или, если виноват не мусор, а код:

  ВЕРДИКТ : ПРОЦЕСС РЕАЛЬНО СЧИТАЛ, GC ни при чём => горячий код.
            Включите /sdebug ticks on, чтобы узнать какой.
  • Важно и честно: stalls сам не назовёт конкретный мод. Он говорит только направление - "это уборка мусора" / "это код" / "это ожидание диска". Кто именно виноват, ищут следующие команды, каждая под своё направление. Куда идти после вердикта:вердикт "ПАУЗА GC" -> это память. Иди в блок "Про утечки" ниже (leak и whodunit), а заодно проверь gc.
  • вердикт "горячий код" -> иди в ticks (назовёт мод сам), затем при желании profile / top для точных цифр.
  • вердикт "ожидание диска / lock" -> это чаще всего железо хостинга, кодом не чинится.

/sdebug env - общее состояние сервера

Когда вводить: в любой момент, сразу после stalls для общего осмотра. Сервер должен просто работать, уборку запускать не нужно - команда читает текущее состояние.

Покажет блок вот такого вида (лишнее убрал):

ServerDebugger: окружение 
  ProcessorCount       : 24
  Server GC            : False        <- вот эта строка важна
  Pause time %         : 18.5         <- и эта
  Memory load          : 6400 МБ / 16000 МБ

Что читать:

  • Server GC - включён ли быстрый режим уборки мусора. False = медленный однопоточный, уборка тормозит сильнее, чем могла бы. Это "плохая настройка" сервера. Как исправить - в разделе "Ускорить уборку мусора" в самом конце. После починки строка станет True.
  • Pause time % - какая доля времени уходит на уборку мусора. Единицы процентов - норма. 15% и выше (как 18.5 в примере) - уборка и есть твоя проблема.
  • Memory load - сколько памяти занято. Близко к пределу - память может стать причиной сама.

Про утечки - две команды по порядку

Если stalls показал вердикт "ПАУЗА GC" - скорее всего это утечка. Ловится в два шага: сначала /sdebug leak проверяет, есть ли она вообще, потом /sdebug whodunit называет виновника. Идут именно в таком порядке.

/sdebug leak - ШАГ 1: есть ли утечка вообще?

Когда вводить: когда память сервера растёт со временем и лаги усиливаются - и обязательно дав серверу поработать (час-два после старта, или после игровой ночи, когда прошло много мобов). На только что запущенном сервере утечка ещё не накопилась, и тест покажет пусто.

Команда проводит уборку мусора вручную (сервер замрёт на пару секунд) и считает, сколько мёртвых мобов её пережили.

"Пережили" = должны были исчезнуть, но кто-то их держит, и уборка не смогла выкинуть. Логика простая: живых мобов уборка не трогает, а вот если давно исчезнувший моб "пережил" уборку - значит его незаконно держат, и это утечка.

Что покажет: процент выживших.

  • Около нуля - утечки нет. На этом с утечками закончили, причину лагов ищи в другом (см. stalls, env).
  • 80% и выше - утечка есть. Переходи к шагу 2 - /sdebug whodunit.

/sdebug whodunit - ШАГ 2: кто виноват в утечке?

Когда вводить: сразу после того, как /sdebug leak показал высокий процент (утечка подтверждена). Раньше смысла нет - если утечки нет, искать виновника незачем.

Эта команда делает так:

  1. Проводит уборку мусора вручную (сервер может замереть на несколько секунд).
  2. Находит всех мёртвых мобов, которых кто-то до сих пор держит.
  3. Прослеживает, кто именно их держит, и по какому моду проходит эта ссылка.
  4. Выдаёт список: какой мод сколько мёртвых объектов удерживает, с именем файла и места в коде.

Настраивать заранее ничего не надо. Результат выглядит так:

     КТО ДЕРЖИТ УТЕЧКУ
  прослежено 14203 объектов до держателя за 8 с
      удержано объектов, по модам    
    14203  <- Rust and Rustbound Creatures
        файл  : RustboundCreatures.dll
        тип   : RustCreaturesReworked.BowtornTuning
        поле  : MoveSpeedBaselines
       18  <- Другой мод
        3  <- ваниль / движок

Первая строка - главный виновник. Дальше решаешь: удалить мод, обновить его, или написать автору о проблеме.

Важный случай: если whodunit показал держателем только "ваниль / движок", а не мод - это, скорее всего, не утечка. Сущности не "держатся" по ошибке, а просто спавнятся быстрее, чем деспавнятся. Для этого случая - команда spawns ниже.


/sdebug spawns - кто спавнит сущности и что копится

Когда вводить: когда растёт число сущностей (мобов, снарядов и т.п.) или есть подозрение, что кто-то плодит их без меры - а leak/whodunit при этом упираются в "ваниль / движок" и не называют мод. Так бывает, когда сущности не "утекли" (никто не держит ссылку), а просто спавнятся быстрее, чем деспавнятся. Это другой класс проблемы, для которого leak/whodunit по своей природе бессильны - и есть эта команда.

Порядок: /sdebug spawns on (включить), дай серверу поработать подольше - минимум час, лучше 2-3 (за 20 минут дисбаланс не проявится), потом /sdebug spawns (без слова - покажет отчёт). Выключить - /sdebug spawns off.

Показывает две таблицы. Пример:

ServerDebugger: спавн / деспавн сущностей
  -_- накопление (спавн - деспавн за окно) -_-
     спавн |  деспавн |    нетто | тип
      1234 |       12 |    +1222 | EntityDrifter
       688 |      696 |       -8 | EntityButterfly
  (большое положительное 'нетто' = тип копится)
  -_- кто спавнит (мод | тип : сколько) -_-
      1234  ваниль / движок | EntityDrifter
        48  Champion and Elite Mobs | EntityDrifter

Как читать: в первой таблице найди тип с большим +нетто - это то, что реально копится (спавнится куда больше, чем уходит). Во второй таблице найди этот же тип - левый столбец назовёт мод-источник (или "ваниль / движок", если плодит сам движок по условиям спавна).

А если у типа нетто около нуля или в минусе (как EntityButterfly в примере) - значит он не копится, уходит нормально, и подозрение с него снимается. Это тоже полезный ответ: например, если ты думал на дрифтеров, а трекер показал по ним минус - значит проблема не в них.


/sdebug ticks - кто грузит сервер тиками (для "горячего кода")

Когда вводить: когда stalls показал вердикт "горячий код" - то есть лаг не от уборки мусора, а от того, что какой-то мод долго считает каждый тик. Это более простой и автоматический способ, чем profile: не нужно заранее вписывать моды в настройку.

Порядок: /sdebug ticks on (включить), поиграй 10-15 минут, потом /sdebug ticks (без слова - покажет отчёт). Выключить - /sdebug ticks off.

Оборачивает тик-методы всех модов и считает, чей код на сервере вызывается чаще всего. Пример:

ServerDebugger: тики модов
  обёрнуто модов       : 53
  -_- как часто тикает каждый мод -_-
   93205  (38%)  Champion and Elite Mobs
   62176  (26%)  Overhaul lib legacy compat
   51724  (21%)  Rustbound Magic

Верхние строки - главные подозреваемые. Плюс, если трекер включён, строка "Main был внутри" в отчёте о зависании заполнится сама, назвав мод, чей тик висел в момент фриза.

Важно: частота тиков - это не время. Мод может тикать часто, но быстро. Трекер сужает круг подозреваемых до 2-3 модов; чтобы узнать, кто именно ест время, впиши верхний мод в WatchedModMarkers и запусти /sdebug profile on и /sdebug top для точных цифр.


/sdebug profile / top - точные цифры по "горячему коду"

Когда вводить: после ticks, когда уже знаешь подозреваемый мод и хочешь точные цифры по времени. В отличие от ticks (частота), profile замеряет именно затраченное время по кускам кода - но только у модов, указанных в настройке WatchedModMarkers.

Порядок: впиши подозреваемый мод (из ticks) в WatchedModMarkers, затем /sdebug profile on, поиграй, потом /sdebug top - покажет, какие методы съели больше всего времени.


/sdebug entities - сколько всего живых мобов в мире

Когда вводить: в любой момент, когда хочешь понять, реально ли мобов много в мире, или они только "висят" в памяти. Полезно рядом с /sdebug leak - вместе они отличают утечку от настоящего наплыва.

Показывает, сколько существ игра сама считает загруженными, с разбивкой по видам и по самым "населённым" участкам карты.

Зачем: отличить утечку от честного наплыва. Если команда показывает 80 000 мобов - они правда в мире, что-то сломало ограничение спавна. Если показывает 200, а /sdebug leak при этом находит тысячи "мёртвых" - значит мобы давно исчезли, но висят в памяти. Это утечка.

Прочее

  • /sdebug gc - гистограмма причин уборок мусора (много Induced = какой-то мод дёргает уборку вручную).
  • /sdebug gchook on + /sdebug gccallers - поймать, какой мод запускает уборку вручную.
  • /sdebug findroot - ручной, более подробный вариант whodunit (полная цепочка ссылок). Нужен редко.
  • /sdebug threshold [мс] - с какой длительности фриз попадает в лог (по умолчанию 500 мс = полсекунды).
  • /sdebug lang [код] - язык вывода (см. ниже).
  • /sdebug reset - очистить накопленную статистику (в памяти).
  • /sdebug clearlog - очистить файл лога (начать с чистого листа).

Как читать блок "стойло" (зависание сервера) или же /sdebug stalls

 

Каждый такой блок - это один пойманный фриз. Ниже разобрана каждая строка на реальном примере.

стойло main-потока
  Время                : 20:19:12.952
  Длительность         : 751.7 мс

Время - когда случился фриз. Длительность - сколько сервер стоял. 751.7 мс = 0.75 секунды сервер не отвечал. Обычный тик длится ~50 мс, так что это в 15 раз дольше нормы - игроки это почувствовали как заминку.

куда ушло время (дельты за окно стойла)
  GC pause             : 697.6 мс  (93%)

Самое важное, разберём подробно.

GC pause - это время, которое сервер простоял из-за уборки мусора (GC = garbage collector, сборщик мусора). Уборка - это когда система замирает, проходит по памяти и выкидывает ненужные объекты. Пока идёт уборка, сервер не тикает.

  • 697.6 мс - сколько именно длилась уборка внутри этого фриза.
  • (93%) - какую долю всего фриза она заняла.

Читается так: фриз был 751.7 мс, и из них 697.6 мс (93%) - это уборка мусора. То есть почти весь фриз - это уборка. Значит виновата именно она, а не что-то другое. Если бы тут стояло (5%) - уборка была бы ни при чём, копать надо было бы в другом месте.

  CPU процесса         : 187.5 мс  (25%)  <- СЧИТАЛ или ЖДАЛ: вот ответ

CPU процесса - сколько за время фриза сервер реально работал процессором (считал), а не просто стоял.

  • 187.5 мс - столько сервер считал.
  • (25%) - это 25% от длительности фриза.

Ключевая мысль: фриз длился 751 мс, а считал сервер всего 187 мс из них. Куда делись остальные 564 мс? Сервер их прождал, ничего не делая. Это отличает «сервер трудился» от "сервер завис в ожидании". Если бы тут было (95%) - сервер честно вкалывал. А (25%) значит - в основном ждал.

  ThreadPool latency   : 5.6 мс

Насколько задерживались фоновые задачи. Мелочь, важна редко. Большое число (секунды) означало бы, что фоновые потоки забиты - здесь всё в норме.

  фон ЗА 9.3 с ДО стойла (вот настоящая нагрузка)
  Аллокации            : 23.0 МБ/с
  CPU процесса         : 20.6% от одного ядра

Это не про сам фриз, а про 9.3 секунды перед ним - чтобы понять, что творилось на сервере в спокойный момент до заминки.

  • Аллокации 23.0 МБ/с - с какой скоростью код создавал в памяти новые временные объекты. Чем выше, тем чаще система вынуждена убирать мусор. 23 МБ/с - умеренно. Сотни МБ/с - это уже мод-мусорщик, который заваливает память и провоцирует частые уборки.
  • CPU 20.6% от одного ядра - насколько сервер был занят перед фризом. 20% - расслаблен. Если бы тут было под 100% - значит сервер и так пыхтел, фриз был на пределе.
  -_- память -_-
  Причина последней GC : gen0, AllocSmall, NonConcurrent (BLOCKING)

Почему запустилась уборка. Расшифровка технических слов:

  • gen0 / gen1 / gen2 - "поколение", глубина уборки. gen0 - лёгкая, быстрая, только свежий мусор. gen2 - полная и тяжёлая, проходит всю память (именно она даёт длинные паузы). Здесь gen0 - самая лёгкая.
  • AllocSmall - причина: "в памяти кончилось место под мелкие объекты". Это естественная уборка, память переполнилась сама. Противоположность - Induced, когда уборку запустил какой-то мод вручную (это уже повод искать виновника).
  • BLOCKING - уборка была "останавливающей": сервер стоял, пока она шла. Бывает Background - фоновая, почти без остановки.
  Сборки за окно       : gen0 +1, gen1 +0, gen2 +0

Сколько уборок каждого уровня случилось за фриз. gen0 +1 - одна лёгкая уборка. Если бы тут было gen2 +1 - это была бы тяжёлая полная уборка, и паузу в сотни мс она объясняла бы полностью.

  Аллоцировано в окне  : 13 МБ  (при замершем main это почти всегда ~0 — не показатель)

Сколько памяти создалось за время фриза. Обычно неинформативно (сервер же стоял), сам мод это и оговаривает - не обращай внимания.

  Heap                 : 4027 МБ -> 4031 МБ

Heap - общий размер памяти под объекты (куча) до и после фриза. Здесь почти не изменился. Если бы после уборки куча заметно упала (например, 4027 > 2800) - уборка нашла много мусора и выкинула. Если не падает при большой куче - это признак утечки (мусор есть, но выкинуть нельзя, его кто-то держит).

 Committed : 4226 МБ, фрагментировано 449 МБ (11% кучи) 
  • Committed - сколько памяти сервер зарезервировал у системы (обычно чуть больше heap).
  • Фрагментировано 449 МБ (11%) - "дырявость" памяти. 11% - терпимо. 25%+ - уже мешает.
  Working set / commit : 4396 МБ / 4509 МБ  (в RAM 97%)

Сколько памяти сервера реально лежит в быстрой оперативке (RAM), а не уехало на медленный диск.

  • в RAM 97% - почти вся память сервера в оперативке. Это хорошо.
  • Если бы тут было, скажем, в RAM 60% - значит 40% памяти система выгрузила на диск (в pagefile), и уборка вынуждена поднимать её обратно с диска - медленно. Это признак нехватки оперативки на машине.
  Page faults за окно  : +1573

Сколько раз за фриз серверу пришлось лезть за памятью на диск, потому что её не оказалось в оперативке. Немного - норма. Тысячи-десятки тысяч - верный знак, что памяти на машине не хватает и она свопится на диск.

  Memory load          : 113274 МБ / 39060 МБ  (порог 124992 МБ, свободно -)

Насколько забита память всей машины (не только твоего сервера - всей физической ноды у хостера).

  • 113274 МБ - сколько занято на машине сейчас.
  • порог 124992 МБ - красная черта, после которой система начинает паниковать и агрессивно убирать мусор.
  • Если первое число подбирается к порогу - памяти на машине в обрез. Это часто не ты, а соседние серверы на той же железке.
  код
  Main был внутри      : Champion and Elite Mobs

Если включён трекер тиков (/sdebug ticks on) или профайлер, тут стоит имя мода, в тик-коде которого сервер застрял в момент фриза. Если оба выключены - будет "(включите /sdebug ticks on)", и информации нет, это нормально для обычного разбора.

  ВЕРДИКТ : GC ЖДАЛ, а НЕ СЧИТАЛ: 187.5 мс CPU за 751.7 мс паузы.
            Это hard page faults — куча выгружена в pagefile,
            GC поднимает её с диска. Проблема в памяти МАШИНЫ.

Готовый вывод простым текстом. Мод сам собирает его из строк выше. Тут он говорит: уборка мусора шла 751 мс, но сервер за это время считал всего 187 мс - остальное ждал диск. Причина - памяти на машине не хватило, часть кучи уехала на диск, и уборка ползала, поднимая её обратно. Это железо хостинга, а не код мода.


Как читать вердикт в двух словах

Всё сводится к сравнению двух чисел: GC pause (сколько стоял из-за уборки) и CPU процесса (сколько при этом реально считал).

  • GC pause большой + CPU почти равен ему > уборка честно работала. Лечится уменьшением кучи или ускорением уборки (Server GC).
  • GC pause большой, а CPU маленький (как здесь: 697 мс паузы, 187 мс счёта) > уборка не считала, а ждала диск. Лечится добавлением памяти на машине - это к хостеру.
  • GC pause ≈ 0, а CPU большой > уборка ни при чём, виноват тяжёлый код. Ищи мод через /sdebug ticks.
  • Всё маленькое > сервер просто ждал (диск или блокировка).

Настройка мода

 

При первом запуске создаётся файл ModConfig/ServerDebuggerConfig.json:

{
  "Language": "en",
  "StallThresholdMs": 500,
  "WatchedModMarkers": [ "xskills", "xlib", "xleveling", "xeffects" ]
}
  • Language - язык вывода по умолчанию.
  • StallThresholdMs - с какой длительности (в миллисекундах) фриз считается достойным записи в лог. 500 = полсекунды.
  • WatchedModMarkers - подсказка для /sdebug profile и /sdebug findroot, на какие моды смотреть по умолчанию. Значения xskills, xlib и т.д. здесь - просто пример (мод изначально писался при отладке этих модов). Это не зависимость: сам ServerDebugger от xskills/xlib не зависит вообще и работает на любом сервере с любыми модами. Если хочешь - сотри их и впиши свои (например, тот, что назвал ticks), или оставь как есть. Главные команды (whodunit, leak, entities, stalls, gc, gccallers, env, ticks, spawns) этот список игнорируют и работают всегда. Обычному пользователю трогать не обязательно.

Язык

 

Сменить язык вывода на лету:

/sdebug lang ru

Выбор сохраняется. Без кода команда покажет текущий язык и список доступных.

Добавить свой язык: скопировать assets/serverdebugger/lang/en.json в файл со своим кодом (например aaa.json) и перевести значения. Плейсхолдеры {0}, {1} и команды /sdebug ... трогать нельзя - только текст вокруг. Файл подхватится сам. Если какой-то строки в твоём файле нет - подставится английская, так что переводить можно постепенно.

Технические слова (названия причин уборки вроде AllocSmall, имена мест в коде в выводе findroot) намеренно не переводятся - это идентификаторы, их нужно видеть как есть.



Ускорить уборку мусора (если env показал Server GC : False)

Это тот самый "как исправить", о котором сказано в описании /sdebug env. Если команда показала Server GC : False на мощном сервере - уборка мусора идёт в один поток, медленно, и паузы длиннее, чем могли бы быть. Лечится правкой одного файла настроек.

Что делать

  1. Через файловый менеджер хостинга найди файл VintagestoryServer.runtimeconfig.json (лежит рядом с самим сервером).
  2. Сначала сделай его копию - на случай, если что-то пойдёт не так, вернёшь как было.
  3. Открой файл. Внутри есть раздел configProperties. Допиши в него три строки (не забудь запятую в конце предыдущей строки):
"System.GC.Server": true,
"System.GC.Concurrent": true,
"System.GC.HeapCount": 6

Файл целиком будет выглядеть примерно так:

{
  "runtimeOptions": {
    "tfm": "net10.0",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "10.0.0"
    },
    "configProperties": {
      "System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
      "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false,
      "System.Runtime.TieredPGO": true,
      "System.GC.Server": true,
      "System.GC.Concurrent": true,
      "System.GC.HeapCount": 6
    }
  }
}
  1. Сохрани файл и сделай полный перезапуск сервера - не "reload", а именно рестарт. Настройка читается только при запуске, иначе не применится.
  2. Проверь: введи /sdebug env. Строка должна стать Server GC : True, а Pause time % - заметно упасть.

Что означают эти строки (простыми словами)

  • Server GC - включает быструю уборку мусора в несколько потоков вместо одного. Это главное.
  • Concurrent - часть уборки идёт в фоне, не останавливая сервер.
  • HeapCount - на сколько ядер разложить уборку. Ставим 6: быстро, но не слишком жадно до памяти (без ограничения уборка заняла бы куда больше памяти).

Чего ожидать

На реальном сервере эта настройка снизила время в паузах с 28% до меньше 1%, а фризы от уборки мусора стали почти незаметными. Это не чинит утечки (утечку надо убирать отдельно, через whodunit), но делает любую уборку в разы быстрее.


Report Page