Итак,
лагом в общем случае можно назвать все внутри-компьютерные явления,
которые мешают нормальной игре. Примеры: "слайд-шоу", зависание
картинки, зависание игровых объектов. Но соседа с дрелью к лагам
отнести нельзя, хотя играть он однозначно мешает.
Все причины лагов можно разделить на: 1) Проблемы на компьютере игрока - их в силах решить сам игрок; 2) Проблемы на канале связи между компьютером игрока и сервером; 3) Проблемы на сервере.
Ниже рассмотрим все это подробнее, но для начала список терминов, используемых в статье.
Список определений
ХЛ, Half-Life
- в статье используется как название движка (но не игры про Гордона
Фримена!). Данные из статьи применимы ко всем модам, созданным на этом
движке, в том числе и для Counter-Strike. Клиент - это
программа (Half-Life), запущенная на компьютере игрока, которая
обменивается данными с сервером и рисует картинку игрового мира. хлдс, HLDS, Half-Life Dedicated Server - это программа такая, собственно серверная часть для Half-Life. Сервер - Компьютер, на котором запускается хлдс Квар, он же CVar, он же Console Variable
- переменная, использующаяся в Half-Lfe, изменяющая какие-либо
параметры игры. Может быть изменена пользователем из консоли (отсюда и
название). Квары используются как на клиенте, так и в хлдс. Квары,
влияющие только на серверную часть, имеют префикс sv_ (примеры -
sv_minrate, sv_maxupdaterate); Квары, влияющие только на клиент имеют
префикс cl_ (cl_lw, cl_lc, cl_updaterate).
Список кваров
Список кваров, назначение которых необходимо знать: 1) Клиентские: cl_updaterate - количество пакетов в секунду, которое клиент хочет получать от сервера (именно хочет, но не факт что получит), 1/сек cl_rate - исходящая полоса пропускание клиента (для данных от клиента к серверу), байт/сек, то есть максимальная скорость передачи данных к серверу. rate
- входящая полоса пропускания клиента (для данных от сервера к
клиенту), байт/сек, или максимальная скорость передачи данных к клиенту net_graph - определяет тип отображения статистики по сетевому подключению. может принимать значения от 0 до 3 (об этом позже)
2) Серверные: sv_maxrate - максимальная скорость отдачи данных для одного клиента, байт/сек sv_minrate - минимальная скорость отдачи данных для одного клиента, байт/сек sv_maxupdaterate - максимальное количество пакетов в секунду, которое может быть передано одному клиенту. sv_minupdaterate - минимальное количество пакетов в секунду, которое может быть передано одному клиенту. sys_ticrate
- определяет максимальное количество кадров, которые сервер может
обсчитать за секунду. В HLDS используется значение 1000/sys_ticrate
(это в миллисекундах) как интервал перерыва между обсчетом кадров.
Матчасть. Как хлдс контролирует поток данных к клиентам.
Отдача данных в хлдс контролируется отдельно для каждого клиента, на основе двух факторов: 1) количество пакетов в секунду, передаваемых клиенту, назовем это значение updrate 2) максимальная скорость передачи к клиенту, назовем это значение cmrate.
I.
Исходными данными для определения 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 пакетов в секунду, тк значение уперлось в нижний
порог.
II. Исходными данными для 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 строчка - FPS, интервал десинхронизации (грубо говоря - пинг), значение cl_updaterate 2 строчка - информация о данных от сервера: текущий размер пакета и средняя скорость приема 3 строчка - информация о данных к серверу: текущий размер пакета и средняя скорость отдачи 4 строчка
- график данных от сервера. Каждая точка - входящий пакет, высота точек
показывает задержку (пинг), чем выше точка, чем больше задержка. Сами
точки могут быть 3-х цветов: зеленые - нормальный пакет, пришел вовремя,
нигде не задержался желтый - пакет с маркером choke, значит сервер не смог отправить все данные из-за политики рейтов; красный
- пакет потерялся на просторах интернета ;). Количество loss
(потерянных пакетов) и choke пакетов можно так же увидеть в цифрах режиме
net_graph 3. Значение, отображаемые там нужно понимать так - сколько
пакетов из последних 100 было потеряно(loss) или переполнено(choke). 5 строчка - текущее значение cl_cmdratre 6 строчка
- два графика (хотя трудно их там разглядеть)Обновляются они синхронно,
каждый столбец соответствует одному кадру, который вырисовывает клиент.
Первый график- высотой в один пиксель в самой нижней части.
Содержит красные точки. Ими помечаются кадры, в которые не были
отправлены cmd пакеты к серверу (можно сказать, аналог choke для
клиента, то есть у клиента есть данные для отправки, но отправить он их
не может, так как время отправки еще не подошло). В случае, если пакеты
отправляются на сервер после отрисовки каждого кадра, графика вообще не
видно. Второй график - фиолетовый в нижней части и красный в верхней -
показывает уровень десинхронизации состояния клиента и сервера. Если
присмотреться внимательно, то он представляет собой гребенку (что-то вроде - //////). Степень десинхронизации зависит от того, когда был
получен последний пакет от сервера. Следствие - при только что
полученном пакете десинхронизация минимальна, а при большой задержке
входящих пакетов - максимальна (график в таком случае превращается в
красную полосу в верхней части)
Примеры, описания и решения
Ниже набор из 6-ти снимков + описание к ним
1.
Симптомы - слайд-шоу, низкий FPS. Причины: железу на клиенте пора на
помойку, либо что-то еще не слабо кушает процессорное время (может
антивирус, или наоборот какие-то вирусы). Решение: Найти и истребить объект, использующий ЦП, либо бежать в магазин за новым компьютером.
2.
Видим красные точечки на зеленом графике - потеря пакетов. Это не
лучший снимок для демонстрации, но ничего другого к сожалению нет.
Симптомы - рывки игроков во время игры, задержка стрельбы или других
действий. Особенно хорошо проявляется, когда теряется несколько пакетов
подряд. Решение: Единого способа нет, так-как причина может быть
независящей от вас (может пьяный админ за кабель запнулся). Что можно
сделать - выключить все что использует сеть, особенно торренты и
закачки. Можно попробовать собрать диагностику ping/traceroute и
отправить в службу поддержки вашего провайдера.
3.
А тут у нас подвисание на компьютере клиента. Симптомы - внезапное
"замирание" игры на 200-300мсек, после чего нормальное продолжение. На
нетграфе сопровождается подскоком зеленого графика "под потолок" (на снимке видно два фриза с небольшим интервалом), при этом на нижнем
графике нет никаких отклонений. Причины - в основном связаны с
драйверами или железом. Фриз, который можно лицезреть на снимке был
вызван "умным" поведением винчестера - после 5-6 секунд бездействия он
паркует блок головок, а при при попытке чтения чего-либо распарковывает
их, при этом вся система ненадолго зависает. Решения - попробовать
поставить "рядом" чистую ОС и посмотреть, будут ли подвисания на ней. Если
будут - это что значит проблема с железом, ищем виновника последовательной заменой
комплектующих. Если же полет нормальный - то дело было в каком-то шибко
умном драйвере. Так же может иметь конфликт железо-железо, либо
железо-драйвер. В общем, единый путь решения найти довольно трудно.
4.
Самая часто встречающаяся сейчас проблема - choke, желтизна на графике,
который должен быть зеленым ;) Симптомы - рост пинга при большом
количестве игроков, либо на картах, где видно одновременно много
объектов, задержка стрельбы, может быть видно передвижение других
игроков и объектов рывками. Причина: Сервер генерирует больше данных, чем может передать. Решение:
Нужно увеличивать скорость, выделяемую клиенту. Ставим rate побольше
(например 300000) и смотрим, что произойдет. Если желтизна исчезла -
можете поздравить себя с решением проблемы Если нет - пытаемся
достучаться админу сервера. Если админом являйтесь вы, то тогда ставим в
хлдсе sv_maxrate побольше (100000 например). Можно так же поднять и
sv_minrate - это поможет игрокам с дефолтным конфигом (там вроде стоит
rate 6000) избежать choke-ов и лагов.
5.
Тут бы наблюдаем явную гребенку на нижнем графике - это означает что
клиент получает данные через слишком большие интервалы времени. В игре
может выражаться небольшим ростом пинга, небольшим подергиванием
объектов, игроков. Причины: низкий cl_updaterate или очень маленький
sv_maxupdaterate на серверное стороне. Лечится увеличением значений
этих переменных. Так же такое поведение может вызываться очень низким
серверным FPS (< 50). Решается разгрузкой процессора на сервере, либо
поднятием значения sys_ticrate (если он имеет малое значение, т.е <
100). Можно еще поставить плагины для увеличения серверного FPS, только
при перегруженном ЦП они не спасут.
6.
Здесь можно лицезреть подвисание на серверной стороне - был очень большой
перерыв между обработками кадров на сервере. На нетграфе выражается
подскоком на нижнем графике десинхронизации, при этом с доставкой
пакетов проблем не было (верхний график в норме). Причин может быть несколько: 1) обычно связано с высокой загрузкой диска на сервере, когда хлдс пытается что-либо прочитать - происходит задержка. 2)
может происходить из-за блокирующих запросов в перегруженную субд.
Решение - переходим на неблокирующие (threaded) запросы, правда тут без
переписывания кода плагинов не обойтись 3) низкий приоритет,
данный хлдсу. Если на сервере нашелся процесс с намного более высоким
приоритетом, чем HLDS, при этом он загрузил весь (все) ЦП, то хлдс
отправляется курить на это время.