Алгоритм Нейгла, который копит мелкие пакеты перед отправкой, и отложенный ACK, который придерживает подтверждения, мешают друг другу, и каждое сообщение, записанное по частям, задерживается на 40–200 ms.
Почему Мелкие сообщения пишутся по частям без включённого TCP_NODELAY → Следствие Отправитель ждёт ACK, а получатель отправляет ACK с задержкой → На экране Пинг низкий, но все действия одинаково запаздывают: задержка ввода
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: включить TCP_NODELAY, собирать сообщения за тик и записывать их за один раз. На отключение отложенного ACK у получателя не полагаться (TCP_QUICKACK в Linux действует недолго, в Windows нужно править реестр на каждом ПК): игра не может надёжно этим управлять. Клиент: включить TCP_NODELAY, собирать сообщения за кадр и записывать их за один раз.
Цифры для ориентира
Отложенный ACK в Linux обычно 40 ms (в зависимости от ситуации до 200 ms). В старых версиях Windows было 200 ms, в современных 40 ms (в стандартном шаблоне Windows Server 2019 тоже 40 ms). Задержку ACK определяет ОС получателя, поэтому, если сервер с включённым Nagle отправляет сообщения по частям, задержка в зависимости от ПК игрока может составлять 40–200 ms.
На графике
Высоко с самого начала · время отклика на действие (RTT внутри игры)
Где смотреть
Посмотреть в захвате пакетов на стороне сервера (tcpdump, Wireshark) интервалы между запросами и ответами и проверить, включает ли код сервера и клиента TCP_NODELAY
Подтверждает
Пинг низкий, но между мелкими пакетами повторяются паузы около 40 ms (в старых версиях Windows 200 ms), и каждая пауза заканчивается сразу после прихода ACK от другой стороны. С TCP_NODELAY паузы исчезают
Опровергает
Если интервал ответа близок к пингу, причина в другом. Если игровой сервер сам поздно формирует ответ, дело в обработке на сервере («Затор в очереди сообщений»)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источники
RFC 9293: Transmission Control Protocol (TCP)IETF Пока есть данные без ACK, алгоритм Нейгла копит мелкие порции. Должна быть возможность отключить его для каждого соединения. Отложенный ACK меньше 0,5 с. Описана проблема их взаимодействия
include/net/tcp.h (Linux v6.12)Linux kernel Отложенный ACK в Linux: минимум TCP_DELACK_MIN (HZ/25 = 40 ms), максимум TCP_DELACK_MAX (HZ/5 = 200 ms)