Buffer de socket do kernel insuficiente Small socket buffers
ID da causa so-sockbuf · Responsável principal Infraestrutura de servidores (Equipe de infraestrutura) · Também envolvidos Desenvolvimento do servidor (Equipe de desenvolvimento)
Com buffers de envio e recepção pequenos, quando chega um burst de tráfego, os pacotes recebidos por UDP são descartados e o envio TCP fica bloqueado por falta de espaço no buffer.
Por quê SO_SNDBUF e SO_RCVBUF no valor padrão ou pequenos demais → Efeito Num burst, ou enquanto a thread de recepção para por um instante, o buffer de recepção UDP transborda e descarta pacotes. No TCP, o envio espera por falta de espaço no buffer de envio → Na tela Teleporte (perda no UDP) ou avanço rápido (espera no TCP)
Responsável principal Infraestrutura de servidores (Equipe de infraestrutura) · Também envolvidos Desenvolvimento do servidor (Equipe de desenvolvimento)
O que fazer (Equipe de desenvolvimento)
Definir no código tamanhos de buffer (SO_SNDBUF e SO_RCVBUF) adequados ao tráfego, lembrar que no TCP definir o tamanho manualmente desliga o ajuste automático do Linux, não exagerar no tamanho (um buffer grande demais acumula dados velhos e aumenta a latência), não deixar a thread de recepção parar.
O que fazer (Equipe de infraestrutura)
Ajustar o teto do kernel (rmem_max e wmem_max; o tamanho definido no código também não passa desse valor) e o padrão (rmem_default), monitorar o contador de estouro do buffer (RcvbufErrors).
Números de referência
O buffer de recepção UDP padrão no Linux é de cerca de 208 KB. Cada pacote, mesmo pequeno, ocupa muito mais memória do kernel do que o seu tamanho real, então de algumas dezenas a centenas de pacotes já enchem o buffer. Em um servidor que recebe 100 mil pacotes por segundo, basta a thread de recepção parar por alguns ms para o buffer transbordar.
No gráfico
Picos aleatórios · Estouros do buffer de recepção UDP (UdpRcvbufErrors)
Onde olhar
Ver o aumento de UdpRcvbufErrors no nstat -az e o skmem do ss -uamn (rb é o tamanho do buffer de recepção; d, os pacotes descartados sem entrar no socket); no TCP, ver no skmem do ss -tm se a memória de envio pendente (w) chegou ao tamanho do buffer de envio (tb)
Confirma se
No momento do burst ou da parada da thread de recepção, UdpRcvbufErrors (ou o d do socket) sobe, e rb está perto do padrão (cerca de 208 KB). No TCP, w fica colado em tb e o send bloqueia
Descarta se
Contador parado, mas com perda: etapa da NIC (“Ring buffer insuficiente”) ou trecho de rede
Como verificar
Ferramentas de infra (sem precisar do código do jogo)
Fontes
socket(7) — Linux manual pageLinux man-pages O padrão de SO_RCVBUF e SO_SNDBUF é rmem_default e wmem_default, o teto é rmem_max e wmem_max, e o kernel dobra o valor configurado
include/net/sock.h (Linux v6.18)Linux kernel Define o buffer de socket padrão como o espaço de 256 pacotes de 256 bytes, incluindo o overhead do sk_buff (SKB_TRUESIZE(256)×256); até frames pequenos contam como sk_buff+MTU (os cerca de 208 KB são o valor calculado em x86-64)
IP SysctlLinux kernel tcp_rmem e tcp_wmem: definir SO_RCVBUF ou SO_SNDBUF manualmente desliga o ajuste automático de tamanho daquele socket
net/ipv4/udp.c (Linux v6.12)Linux kernel Quando a fila de recepção UDP passa do tamanho do buffer do socket, o pacote é descartado na hora e RcvbufErrors sobe
net/ipv4/proc.c (Linux v6.12)Linux kernel Nomes dos contadores mostrados pelo nstat: RcvbufErrors e SndbufErrors do grupo Udp
ss(8) — Linux manual pageiproute2 skmem do -m: rb, tamanho do buffer de recepção; tb, tamanho do buffer de envio; w, memória de envio pendente; d, pacotes descartados antes de entrar no socket