Вступление
Итак, лагом в общем случае можно назвать все внутри-компьютерные явления, которые мешают нормальной игре.
Примеры: "слайд-шоу", зависание картинки, зависание игровых объектов. Но соседа с перфоратором к лагам отнести нельзя, хотя играть он мешает
Все причины лагов можно разделить на:
1) Проблемы на компьютере игрока - их в силах решить сам игрок;
2) Проблемы на канале связи между компьютером игрока и сервером;
3) Проблемы на сервере.
Ниже рассмотрим все это подробнее, но для начала список терминов, используемых в статье.
Список определений
ХЛ, Half-Life - в статье используется как название движка
(но не игры про Гордона Фримена!). Данные из статьи применимы ко всем модам, созданным на этом движке, в том числе и для Counter-Strike.
Клиент - это программа
(Half-Life), запущенная на компьютере игрока, которая обменивается данными с сервером и рисует картинку игрового мира.
HLDS, Half-Life Dedicated Server - это программа такая, собственно серверная часть для Half-Life.
Сервер - Компьютер, на котором запускается хлдс.
Квар, он же CVar, он же Console Variable - переменная, использующаяся в Half-Lfe, изменяющая какие-либо параметры игры. Может быть изменена пользователем из консоли
(отсюда и название).
Квары используются как на клиенте, так и в хлдс. Квары, влияющие только на серверную часть, имеют префикс
sv_ (примеры - sv_gravity, sv_clienttrace);
Квары, влияющие только на клиент имеют префикс
cl_ (cl_lw, cl_lc, cl_updaterate).
Матчасть. Как хлдс контролирует поток данных к клиентам.
Отдача данных в хлдс контролируется отдельно для каждого клиента, на основе двух факторов:
1) Количество пакетов в секунду, передаваемых клиенту, назовем это значение
updrate
2) Максимальная скорость передачи к клиенту, назовем это значение
cmrate.
Исходными данными для определения
updrate служат три переменные - это клиентская
cl_updaterate, и серверные
sv_maxupdaterate и
sv_minupdaterate.
Алгоритм определения
updrate можно записать так:
updrate := cl_updaterate;
if updaterate > sv_maxupdaterate then updaterate = sv_maxupdaterate;
if updaterate < sv_minupdaterate then updaterate = sv_minupdaterate;
Видно, что по умолчанию
updrate равен клиентскому значению. Однако оно не должно вылазить за пределы максимальных и минимальных значений, определенных в хлдс.
Вот несколько примеров для лучшего понимания:
cl_updaterate = 30,
sv_minupdaterate = 20,
sv_maxupdaterate = 60. В Этом случае клиент будет получать от сервера 30 пакетов в секунду, т е что клиент хотел, то и получил.
cl_updaterate = 100,
sv_minupdaterate = 20,
sv_maxupdaterate = 60. В Этом случае клиент будет получать от сервера 60 пакетов в секунду, тк значение уперлось в верхний порог.
cl_updaterate = 10,
sv_minupdaterate = 20,
sv_maxupdaterate = 60. В Этом случае клиент будет получать от сервера 20 пакетов в секунду, тк значение уперлось в нижний порог.
Исходными данными для
cmrate служат значения клиентской переменной
rate и серверных
sv_maxrate и
sv_minrate. Алгоритм определения точно такой же, как и у
updrate, то есть по умолчанию
cmrate =
rate, однако если значения вылазит за пределы
sv_minrate или
sv_maxrate, то оно ограничивается.
Матчасть. Как хлдс формирует пакеты. Что такое choke. (Упрощенный вариант)
При работе хлдс все данные, которые должны быть посланы клиенту, складываются в отдельный буфер
(он свой для каждого клиента), где и ждут момента, когда подойдет время их пересылки. Как только время подошло, данные начинаются записываться в пакет.
На размер пакета накладывается ограничение по
cmrate, чтобы не перегрузить полосу, отведенную клиенту. Максимальный размер пакета, связанный с этим ограничением, может быть вычислен как
cmrate/
updrate, то есть максимальная скорость делится на количество пакетов в секунду.
Но что будет, если данных сервер сгенерировал больше, чем может отправить? Тогда все просто - в пакет записываются только данные, которые укладываются в максимальный лимит, остальные остаются ждать следующей пересылки. Так же в пакет дописывается однобайтовое сообщение
svc_choke, которое сигнализирует о том, что хлдс не смог послать все данные, которые сгенерировал.
Да, эти данные придут к клиенту в следующем пакете, однако придут они уже с задержкой. А если очередь данных на хлдсе разрастается и никогда не заканчивается, то на клиенте можно наблюдать нехилый такой рост пинга, и значение
choke = 99
(его можно посмотреть в net_graph 3).
Отдельным пунктом стоит отметить то, что проверка на размер пакета осуществляется только если сервер работает в Internet режиме
(sv_lan 0). При
sv_lan 1 эта проверка отключается. Это может быть причиной появления лагов при переводе хлдса на
sv_lan 0 при ненастроенных
sv_maxrate/
sv_minrate.
Проводим диагностику.
Итак, чтобы избавиться от лагов, надо знать их причину. А причину нам поможет узнать очень хорошее встроенное в хл средство под названием
net_graph, которое отображает в реальном времени информацию, связанную с передачей данных. Имеется 3 режима отображения, мы будем пользоваться первым
(net_graph 1).
Для начала дадим описание того, что там вообще отображается:
1 строчка - фпс, интервал десинхронизации
(грубо говоря - пинг), значение
cl_updaterate
2 строчка - информация о данных от сервера: текущий размер пакета и средняя скорость приема
3 строчка - информация о данных к серверу: текущий размер пакета и средняя скорость отдачи
4 строчка - график данных от сервера. Каждая точка - входящий пакет, высота точек показывает задержку
(пинг), чем выше точка, чем больше задержка. Сами точки могут быть 3-х цветов:
зеленые - нормальный пакет, пришел вовремя, нигде не задержался
желтый - пакет с маркером
choke, значит сервер не смог отправить все данные из-за политики рейтов
красный - пакет потерялся на просторах интернета
Количество
loss (потерянных паетов) и
choke пакетов можно так же увидеть в цифрах режиме
net_graph 3. Значение, отображаемые там нужно понимать так - сколько пакетов из последних 100 было потеряно
(loss) или переполнено
(choke).
5 строчка - текущее значение
cl_cmdratre
6 строчка - два графика
(хотя трудно их там разглядеть), обновляются они синхронно, каждый столбец соответствует одному кадру, который отрисовывает клиент.
Первый график - высотой в один пиксель в самой нижней части. Содержит красные точки. Ими помечаются кадры, в которые не были отправлены
cmd пакеты к серверу
(можно сказать, аналог choke для клиента, то есть у клиента есть данные для отправки, но отправить он их не может, так как время отправки еще не подошло). В случае, если пакеты отправляются на сервер после отрисовки каждого кадра, графика вообще не видно.
Второй график -
фиолтеовый в нижней части и
красный в верхней - показывает уровень десинхронизации состояния клиента и сервера. Если присмотреться внимательно, то он представляет собой гребенку (типа вот так - //////). Степень десинхронизации зависит от того, когда был получен последний пакет от сервера. Следствия - при только что полученном пакете десинхронизация минимальна, а при большой задержке входящих пакетов - максимальна
(график в таком случае превращается в красную полосу в верхней части)
Примеры, описания и решения
Ниже набор из 6-ти скриншотов + описание к ним
График 1
Симптомы - слайд-шоу, низкий фпс.
Причины: железу на клиенте пора на помойку, либо что-то еще нехило кушает процессорное время
(может антивирус, или наоборот какая-то вирусня).
Решение: Найти и истребить объект, использующий ЦП, либо бежать в магазин за новым компьютером.
График 2
Видим красные точечки на зеленом графике - потеря пакетов. Это не лучший скрин для демонстрации, но ничего другого нет к сожалению.
Симптомы - рывки игроков во время игры, задержка стрельбы или других действий. Особенно хорошо проявляется, когда теряется несколько пакетов подряд.
Решение: Единого способа нет, т к причина может быть независящей от вас (может пьяный одмин за кабель запнулся). Что можно сделать - вырубить все, что использует сеть, особенно торренты и закачки. Можно попробовать собрать диагностику
ping/traceroute и отправить в саппорт провайдера
График 3
А тут у нас фриз на компьютере клиента.
Симптомы - внезапомное "замирание" игры на 200-300 мсек, после чего нормальное продолжение. На
нетграфе сопровождается подскоком зеленого графика "под потолок"
(на скрине видно два фриза с небольшим интервалом), при этом на нижнем графике нет никаких отклонений.
Причины - в основном связаны с драйверами или железом. Фриз, который можно лицезреть на скрине был вызван "умным" поведением винчестера - после 5-6 секнуд не активности он паркует блок головок, а при при попытке чтения чего-либо распарковывает их, при этом вся система ненадолго зависает.
Решения - попробовать поставить "рядом" чистую ОС и посмотреть, будут ли фризы на ней. Если будут - проблема с железом, ищем виновника последовательной заменой комплектующих. Если же полет нормальный - дело было в каком-то шибко умном драйвере. Так же может иметь конфликт железо-железо, либо железо-драйвер. В общем, единый путь решения найти трудно.
График 4
Самая часто встречающаяся сейчас проблема - choke, желтизна на графике, который должен быть зеленым ;)
Симптомы - рост пинга при большом количестве игроков, либо на картах, где видно одновременно много объектов, задержка стрельбы, может быть видно передвижение других игроков и объектов рывками.
Причина: Сервер генерирует больше данных, чем может передать.
Решение: Нужно увеличивать скорость, выделяемую клиенту. Ставим
rate побольше
(например 500000) и смотрим, что произойдет. Если желтизна исчезла - можете поздравить себя с решением проблемы. Если нет - пытаемся достучаться админу сервера.
Если админом являйтесь вы, то тогда ставим в хлдсе
sv_maxrate побольше
(100000 например). Можно так же поднять и
sv_minrate - это поможет игрокам с дефолтным конфигом
(там вроде стоит rate 6000) избежать
choke-ов и лагов.
График 5
Тут бы наблюдаем явную гребенку на нижнем графике - это означает что клинет получает данные через слишком большие интервалы времени. В игре может выражаться небольшим ростом пинга, небольшим подергиванием объектов, игроков.
Причины: низкий
cl_updaterate или очень маленький
sv_maxupdaterate на серверное стороне. Лечится увеличением значений этих переменных. Так же такое поведение может вызываться очень низким серверным
ФПС (< 50).
Решается разгрузкой процессора на сервере, либо поднятием значения
sys_ticrate (если он имеет малое значение, т е < 100). Можно еще поставить плагины для увеличения серверного фпс, только при перегруженном ЦП они не спасут.
График 6
Здесь можно лицезреть фриз на серверной стороне - был очень большой перерыв между обработками кадров на сервере. На нетграфе выражается подскоком на нижнего графике десинхронизации, при этом с доставкой пакетов проблем не было
(верхний график в норме).
Причин несколько:
1) обычно связана с высокой загрузкой диска на сервере, когда хлдс пытается что-либо прочитать - происходит задержка.
2) может происходить из-за блокирующих запросов в перегруженную субд.
Решение - переходим на неблокирующие
(threaded) запросы, правда тут без переписывания кода плагинов не обойтись.
3) низкий приоритет, данный хлдсу. Если на сервере нашелся процесс с намного более высоким приоритетом, чем хлдс, при этом он загрузил весь
(все) ЦП, то хлдс отправляется курить на это время.
Источник статьи:
hlds.us
Автор: berq