Более точный расчёт времени отклика

Для начала позвольте кратко объяснить непосвящённым кое-какие термины, которые я буду часто упоминать в статье.
Клиент и сервер: все консоли, мобильные устройства, ПК и Mac — это клиенты. Клиент подключается к выделенному серверу, на котором запущена игра. Сервер отвечает за состояние игры в целом (местоположение игроков, состояние кругов, наполнение сундуков и многие другое). Сервер также обязан сообщать клиентам обо всех изменениях в состоянии игры.
Пакет — это совокупность данных, передаваемых по сети от клиента к серверу и наоборот. Клиенты и сервер используют пакеты для общения. Мы используем пакеты для расчёта времени отклика в Fortnite (и UE4).
Кадр — это показатель, насколько часто сервер выполняет все свои действия: проверяет наличие новых пакетов, обновляет состояние игры и рассылает обновления клиентам. На стороне клиента кадр определяет, как часто обновляется изображение на экране. Частота кадров — это количество кадров, которые успевает обработать клиент или сервер за секунду. Таким образом, говоря, что клиент работает со скоростью 60 кадров в секунду, мы подразумеваем, что за секунду обработано 60 кадров.
Теперь, когда вы знаете термины, давайте поговорим о сетевом отклике!
Как мы раньше вычисляли время отклика для пакетов
Многие подразумевают под откликом количество времени, которое тратит клиент, чтобы отправить пакет на сервер, а затем получить ответ (или наоборот). Его ещё называют «временем кругового пути». Именно это значение интересно большинству игроков — оно показывает, насколько быстро их клиенты получают обновления от сервера и насколько быстро сервер получает данные от клиентов. Чем больше время отклика у игрока, тем больше вероятность, что он увидит визуальные артефакты, например телепортирующихся соперников, что он будет внезапно уничтожен, не сможет сразу использовать сундук или какой-либо другой объект.Мы отображаем время отклика в миллисекундах. Чем меньше это значение, тем выше качество связи. Если вам повезло жить по соседству с центром обработки данных, где находятся серверы, ваше время отклика, скорее всего, измеряется однозначным числом! Правда, если вы решите сыграть на сервере, расположенном в другом конце света, задержка увеличится до 100 мс или даже больше.
Однако, клиент-серверное взаимодействие определяется не только скоростью, с которой пакеты данных передаются туда и обратно. В Fortnite мы обычно проверяем, есть ли новые пакеты, только один раз в начале кадра — как на сервере, так и на клиенте. Из-за этого может возникнуть задержка, равная порой целому кадру, если пакет прибыл сразу после того, как клиент или сервер проверил наличие новых пакетов. Кроме того, программа тратит некоторое время, чтобы прочитать пакет и обновить состояние игры в соответствии с содержимым.
Вот диаграмма для наглядности:
Чёрные стрелки клиента и сервер а обозначают время. В этом примере клиент и сервер полностью синхронизированы и работают с одинаковой частотой кадров. Чёрными вертикальными линиями обозначено начало каждого кадра. Синие деления отмечают моменты, когда клиент или сервер ищет новые пакеты для обработки. Оранжевые линии — отправка пакетов клиентом или сервером. Фиолетовые пунктирные линии обозначают пакет данных, передаваемый через интернет.
Вот как выглядит эта последовательность событий:
- Клиент отправляет пакет на сервер.
- Сервер получает пакет, отправленный клиентом.
- Сервер проверяет наличие новых пакетов — именно в этот момент сервер обнаруживает пакет, отправленный клиентом. Заметьте, что этот пакет прождал почти целый кадр, потому что прибыл сразу после того, как сервер проверил наличие новых пакетов.
- Сервер отправляет клиенту сообщение о том, что пакет получен.
- Клиент получает ответ сервера.
- Клиент читает ответ сервера.
Перед выводом значения на экран мы рассчитываем среднее арифметическое для серии пакетов на протяжении нескольких секунд, чтобы сгладить резкие колебания.
К сожалению, в действительности это значение не настолько точное, как нам того бы хотелось. Оно не учитывает период, когда прибывшие пакеты дожидаются обработки, поэтому игроки часто видят завышенное время отклика. Проблема состоит в том, что на большинстве платформ нет возможности узнать, когда именно прибыл конкретный пакет, и поэтому мы не знаем, сколько миллисекунд нужно вычесть.
Как мы вычисляли время отклика для пакетов в версии 7.30
В версии 7.30 мы решили опробовать новый метод: что, если мы будем учитывать только те пакеты, у которых ушло меньше всего времени на передачу от клиента до сервера и получение ответа? Мы предположили, что пакеты, потратившие минимальное время, сразу попадают на обработку, а значит, мы можем смело игнорировать время ожидания, ведь оно почти нулевое. В результате мы стали брать для расчётов 25% самых быстрых пакетов, поскольку нам казалось, что мы нащупали удачный баланс: с одной стороны, мы учитывали только самые быстрые пакеты, но, с другой, использовали достаточное количество данных, чтобы получить реалистичное значение.Что же пошло не так?
После выхода версии 7.30 игроки стали часто сообщать о том, что время отклика не превышает 10 мс, а порой и вовсе равно 0. Будь так на самом деле, это бы означало, что мы отправляем пакеты со сверхзвуковой скоростью. Наш UE4 крут, но пока не настолько! Значит, где-то явно ошибка.Проблема частично связана с формулой расчёта. Напомню её:
Ошибка возникала при вычитании длительност и кадра на сервере. Учитывая только самые быстрые пакеты, мы вычитали слишком много. Если пакет попадает на обработку сразу по прибытии на сервер, программа тратит всего несколько миллисекунд на то, чтобы изучить его содержимое и отправить ответ. Общая длительность кадра на сервере порой в 5 раз больше!
Вот как это выглядит на диаграмме:
Частота кадров этого клиента значительно выше серверной. Поскольку мы учитываем только зелёные пакеты, которые попадают на сервер сразу перед проверкой новых поступлений. Таким образом, сервер работает с частотой, которая превышает максимальное установленное значение, а значит, бездействует в начале кадра до поиска новых пакетов.
Мы вычитаем красную линию, отображающую частоту кадров на сервере, но правильной является оранжевая. Мы явно вычитаем слишком много времени, поэтому некоторые клиенты видят нулевое время отклика.
Даже если использовать старый метод, в котором мы учитывали разные виды пакетов, это всё равно создаёт проблему. Но, поскольку в расчёты попадают пакеты, подолгу ждущие обработки, они компенсируют пакеты, из-за которых мы вычитали слишком много времени.
Планы на будущее
Мы планируем улучшить расчёт времени отклика в будущих обновлениях, чтобы повысить точность отображаемого значения. Как я уже отметил выше,
проблема состоит в том, что на большинстве платформ нет возможности узнать, когда именно прибыл конкретный пакет, и поэтому мы не знаем, сколько миллисекунд нужно вычесть.
К счастью, Linux позволяет это сделать! Поскольку наши серверы работают только под управлением Linux, мы можем изменить формулу расчёта:
Время отклика = время на передачу пакета до сервера + время на передачу пакета до клиента – время от прибытия пакета на сервер до отправки ответа – длительность кадра на клиенте до начала обработки.
Таким образом, нам больше не придётся гадать, вычитая длительность кадра на сервере. Мы ожидаем, что новая формула позволит добиться более точного результата, но сначала её нужно протестировать.
Кроме того, мы планируем чаще проверять новые пакеты на клиенте, чтобы убрать из расчётной формулы длительность кадра на клиенте до начала обработки.
Мы надеемся, что эти изменения помогут нам гораздо точнее рассчитывать время отклика.
Заключение
Надеюсь, мне удалось объяснить, как мы определяем время отклика и что планируем сделать для повышения точности этих расчётов. Информация такого рода непременно должна быть точной, ведь неверные значения вреднее, чем их отсутствие. Если частые промахи или «лаги» вызваны большим временем отклика, игроки должны знать об этом, чтобы у них была возможность решить проблему.
Я буду читать комментарии к этой статье и по возможности отвечать на вопросы. Спасибо за внимание!