Versão interativa: https://jungrok5.github.io/mmo-lag-anatomy/pt-br/ Páginas de causa: https://jungrok5.github.io/mmo-lag-anatomy/pt-br/c/[ID da causa].html # Guia do Lag em Jogos: base de conhecimento Gerado automaticamente (2026-10-03, `node tools/export.cjs`). Não edite à mão: altere src/js/ e gere de novo. 228 causas, 135 termos. As causas são identificadas pelo **ID**. Acrescente `#c-ID` ao endereço do site para abrir o card da causa. ## Códigos de responsável | Código | Equipe | Responsável | Escopo | |---|---|---|---| | cli | Equipe de desenvolvimento | Desenvolvimento do cliente | Código do cliente do jogo: frames, GC e carregamento, interpolação, extrapolação e predição, tratamento de rede no cliente (inclusive envio de heartbeat e reconexão automática) | | srv | Equipe de desenvolvimento | Desenvolvimento do servidor | Código do servidor do jogo: ticks, threads e locks, design de sincronização, aceitação de conexões (loop de accept e argumentos do listen), resposta a heartbeats e limpeza de conexões mortas, opções de socket, design de queries e transações | | net | Equipe de infraestrutura | Infraestrutura de rede | Links e equipamentos de rede do data center (switches, roteadores, firewalls, load balancers, proteção contra DDoS), ACLs de rede, rotas de VPC e load balancers na nuvem, operadoras e peering | | sys | Equipe de infraestrutura | Infraestrutura de servidores | Servidores físicos e instâncias na nuvem (inclusive grupos de segurança e rastreamento de conexões), configuração do SO e do kernel, NIC, ambiente de deploy e monitoramento | | dba | Equipe de infraestrutura | Infraestrutura de banco de dados | Servidores de banco de dados e storage, configuração, replicação e backup do banco, servidores de cache | | ext | Externo | Externo | PC e rede doméstica do jogador, trecho da operadora (fora do nosso contrato), provedores de nuvem. Como não dá para corrigir diretamente, a resposta é orientar, solicitar ou contornar | Em cada causa, o “responsável principal” é quem elimina a causa-raiz, e “também envolvidos” são as equipes que têm trabalho real a fazer. ## Sintomas - **Engasgos** (`stutter`, também chamado de: travadinhas, stuttering, parece queda de FPS): O movimento perde a fluidez e alterna breves paradas com movimento, várias vezes seguidas. Se o ping está normal, o problema provavelmente está nos frames do seu PC (cliente ou SO). Se o ping oscila, a causa mais provável é o jitter do Wi-Fi ou da conexão. Só que o ping exibido no jogo costuma ser medido dentro do game loop, que roda a cada frame, então quando os frames oscilam o número do ping pode oscilar junto. - **Teleporte** (`teleport`, também chamado de: warp, teleportando, trava e pula): O personagem vai de uma vez para uma posição distante, sem mostrar o trajeto. Em geral significa que os pacotes pararam de chegar por um tempo. Suspeite de perda de pacotes, quedas rápidas da conexão, paralisação do servidor e falha na extrapolação. Se só uma pessoa teleporta e o resto está normal, a primeira suspeita é a conexão dela. - **Rubber banding** (`rubber`, também chamado de: puxado para trás, efeito elástico, rollback de posição): Seu personagem avança e é puxado de volta para o ponto por onde acabou de passar. Sua tela (a predição) e a decisão do servidor divergiram. Seu comando não chegou ao servidor (perda), a validação de movimento do servidor o cortou, ou os dois lados calculam o movimento de forma diferente. - **Avanço rápido** (`burst`, também chamado de: tudo de uma vez, jogo acelerado, ações processadas juntas): A tela, que estava parada, volta a andar, e todos os movimentos, golpes e danos atrasados passam depressa, de uma vez só. Os pacotes ficaram acumulados em algum ponto e foram liberados de uma vez. Os casos típicos são a espera por retransmissão TCP, o servidor recuperando o atraso e o cliente com o processamento atrasado. - **Câmera lenta** (`slowmo`, também chamado de: mundo lento, tudo arrastado): Tudo se move devagar. O cast das skills e o movimento dos monstros parecem esticados. Dependendo do design do servidor, a velocidade continua a mesma e o problema aparece como engasgos ou teleporte. O servidor não consegue terminar os ticks no tempo. A conexão está boa, então o ping medido fora do jogo não muda; o ping exibido no jogo pode subir um pouco se incluir a espera pelo processamento no servidor. Verifique pico de jogadores, cálculo de visibilidade, broadcast e falta de memória. - **Input lag** (`delay`, também chamado de: delay nos comandos, resposta lenta, controle pesado): Existe uma demora entre apertar o botão e ver o resultado. A imagem em si pode continuar fluida. O tempo de ida e volta (ping) está alto ou há fila acumulada em algum ponto. Verifique a distância, a fila do roteador, o Nagle (recurso do TCP que junta pacotes pequenos antes de enviar) e as filas do servidor. Se o ping está baixo e tudo continua lento, olhe para o seu PC (V-Sync, FPS baixo) ou para um design que espera a confirmação do servidor a cada ação (capítulo sobre modelos de sincronização). - **Travamento** (`freeze`, também chamado de: congelou, tela parada, não está respondendo): Tudo na tela para por um instante (de 0,5 s a alguns segundos) e depois volta a se mover. O servidor parou por inteiro (GC, deadlock, chamada síncrona), a conexão caiu por um instante ou o seu PC travou. - **Ação perdida / rollback** (`dropped`, também chamado de: skill não saiu, item voltou, troca falhou): Uma ação que você com certeza fez é desfeita, ou o resultado é revertido bem depois. O pedido se perdeu (perda de pacotes, estouro de fila), o servidor decidiu diferente do que sua tela mostrou (diferença no momento da decisão, rejeição depois do feedback no cliente) ou o salvamento falhou no meio (lock ou falha no banco de dados, crash do servidor). - **Desconexão** (`disconnect`, também chamado de: caí do jogo, DC, “A conexão com o servidor foi perdida”): A conexão cai durante a partida e o jogo volta para a tela de login ou para a janela de reconexão. Nenhum pacote chegou dentro do timeout. Verifique quedas longas da conexão, timeout de inatividade, crash ou reinício do servidor, e servidor ou PC parados por mais tempo que o timeout (carregamento longo). Se o jogo fechou sozinho sem aviso, verifique primeiro um encerramento forçado do cliente (crash, falta de memória); a conexão vem depois. - **Não conecta / loading infinito** (`noconnect`, também chamado de: não consigo logar, loading não termina): Você não consegue entrar no jogo ou fica preso na tela de carregamento ou de entrada. O que recebe as conexões novas (fila de conexões do servidor, firewall, servidor de login, banco de dados) está lotado. É especialmente comum logo depois de uma manutenção. - **Invisível / entidade fantasma** (`invisible`, também chamado de: NPC sumido, personagem invisível, monstro morto ainda em pé): NPCs, monstros ou jogadores que deveriam estar ali não aparecem só na sua tela, ou entidades que já sumiram continuam só na sua tela. Em geral, um pacote específico se perdeu ou o desenho falhou, o que tem pouco a ver com velocidade. Verifique diferença de canal ou de phasing, perda da mensagem de spawn ou despawn, descarte durante o carregamento e falha no carregamento de assets. A pista decisiva é ver se a entidade aparece quando você sai do campo de visão e volta. ## Os quatro fatores - **Latência** (`lat`, Latency): Distância, filas e tempo de processamento fazem todos os pacotes chegarem atrasados, de forma constante. Como os jogos lidam com isso: Predição e feedback no cliente mostram sua ação na hora, e o servidor volta no tempo para decidir se o golpe acertou (compensação de lag). - **Jitter** (`jit`, Jitter): A média está boa, mas alguns pacotes chegam cedo e outros chegam tarde. Wi-Fi, conexão congestionada e CPU ocupada causam isso. Como os jogos lidam com isso: O jogo guarda um pouco no buffer de interpolação e tira de lá em ritmo constante para desenhar. Se o jitter for maior que o buffer, não dá para esconder. - **Perda de pacotes** (`loss`, Packet loss): Filas cheias, interferência e equipamentos com defeito descartam pacotes. Uma queda rápida da conexão também é perda de pacotes, só que de vários pacotes seguidos. Como os jogos lidam com isso: Jogos em UDP preenchem as lacunas com interpolação e extrapolação, e seus comandos vão repetidos em pacotes seguidos, então perder um ou dois não faz falta. O TCP não entrega ao jogo os pacotes seguintes até receber de novo o que se perdeu. - **Paralisação** (`stall`, Stall): O tick do servidor atrasa ou para (GC, locks, chamadas síncronas, sobrecarga), ou os frames do seu PC param. Acontece mesmo com a conexão perfeita. Como os jogos lidam com isso: O jogo recupera o atraso processando tudo o que acumulou de uma vez, pula essa parte ou deixa o tempo correr mais devagar. ## Causas ### L1 Processo do jogo no cliente (16 causas) #### cg-hitch · Picos de frame time · Frame hitch Um frame leva várias vezes mais que o normal para ser calculado, e a imagem para por um instante. - Por quê → Efeito → Na tela: Explosão de efeitos de skill, spawn em massa e atualização da UI inteira se acumulam no mesmo frame → O frame não termina em 16,7 ms e leva 50–300 ms → A imagem dá um engasgo e, no frame seguinte, todos se movem de uma vez - Sintomas: Engasgos, Travamento / Fatores: Paralisação - Quem: Só eu / Quando: Quando junta muita gente, Ao fazer ações específicas, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Dividir o trabalho pesado entre vários frames, encontrar com um profiler os frames que dão pico, limitar o número de efeitos. - Números de referência: Em 60 FPS, um frame dura 16,7 ms. Basta um único frame acima de 50 ms para o jogador sentir que o jogo “engasgou”. - No gráfico: Picos aleatórios (Frame time) - Onde olhar: Gravar com o PresentMon, durante o jogo, o frame time (FrameTime) e o tempo que a CPU e a GPU gastaram em cada frame (CPUBusy, GPUBusy). No mobile, as métricas de sessões lentas e de renderização lenta do Android vitals - Confirma se: O frame time, normalmente perto de 16,7 ms, dispara acima de 50 ms em momentos que coincidem com efeitos de skill, spawns em massa ou atualização da UI inteira, e o ping não muda nesses momentos - Descarta se: Frame time estável, mas só os outros personagens dão engasgos: aponta para a rede, como “Buffer de interpolação ausente ou curto demais”. Picos em intervalos regulares: verifique primeiro “Coleta de lixo (GC) no cliente” - Como verificar: Verificação no ambiente do jogador - Fontes: - [Slow rendering](https://developer.android.com/topic/performance/vitals/render) · Android (Google) · Para rodar a 60 FPS, cada frame precisa ser desenhado em 16 ms; se atrasar, frames são pulados e aparecem como engasgos (jank) - [Slow Sessions (games only)](https://developer.android.com/topic/performance/issues/slow-session) · Android (Google) · O Android vitals considera lento o frame de jogo que passa de 50 ms (20 FPS) ou de 34 ms (30 FPS) - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · FrameTime (tempo de CPU entre frames), CPUBusy e GPUBusy (tempo que a CPU e a GPU gastaram para produzir aquele frame) #### cg-gc · Coleta de lixo (GC) no cliente · Client GC (Unity C#, Unreal, Lua) O jogo inteiro para enquanto a memória usada e descartada (lixo) é recuperada. O sinal típico são engasgos em intervalos regulares. - Por quê → Efeito → Na tela: A cada frame, strings, arrays e listas temporárias são criadas e descartadas → Quando o lixo se acumula, o GC pausa a thread principal e recupera a memória → Engasgos regulares, a intervalos de alguns a dezenas de segundos - Sintomas: Engasgos, Travamento / Fatores: Paralisação - Quem: Só eu / Quando: Em intervalos regulares, Quando junta muita gente - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Reduzir alocações (evitar concatenação de strings, LINQ e captura em lambdas), usar object pool, manter o GC incremental ligado (padrão desde o Unity 2020), rodar o GC antes da hora em momentos em que uma pausa não incomoda, como telas de carregamento. - Números de referência: Em geral, de alguns ms a 100 ms por coleta; mais que isso em celulares mais fracos ou em jogos que usam muita memória (na simulação, cerca de 150–170 ms). O GC do Unity verifica o heap inteiro a cada execução, por isso demora mais quanto mais memória o jogo estiver usando. - No gráfico: Picos em intervalos regulares (Frame time, horário de execução do GC) - Onde olhar: Em build de desenvolvimento, os marcadores GC.Collect e GC.Alloc no Profiler do Unity. No Unreal, stat GC e stat Hitches (registra em log os frames que passam do tempo definido em t.HitchFrameTimeThreshold) - Confirma se: Todo frame com pico tem um trecho de GC.Collect com duração parecida com a do pico, a intervalos regulares de alguns a dezenas de segundos. Onde há muita gente, o GC.Alloc por frame aumenta - Descarta se: Frames com pico sem nenhum trecho de GC: aponta para “Carregamento síncrono e compilação de shaders na thread principal” ou “Carga de renderização com muitos personagens” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: É comum em clientes que usam C#, como os feitos em Unity. Os principais culpados são trechos de código que criam a cada frame novas strings de log de combate, números de dano e textos de UI. Se o jogo só engasga onde há muita gente, existe código que gera lixo em proporção ao número de jogadores. O GC incremental divide a coleta em pequenas partes a cada frame (3 ms por padrão no Unity), mas, se o jogo gerar lixo mais rápido do que a coleta consegue recuperar, acaba parando tudo de uma vez. O Unreal Engine também tem um GC próprio, que limpa objetos de jogo que não estão mais em uso; depende da versão e da configuração da engine, mas, na configuração padrão, ele roda mais ou menos a cada 1 minuto e pode causar engasgos em intervalos de 1 minuto. Em clientes que escrevem as regras do jogo em uma linguagem de script como Lua, o GC desse script também roda à parte. - Fontes: - [Garbage collection modes](https://docs.unity3d.com/Manual/performance-incremental-garbage-collection.html) · Unity · O GC incremental é o padrão e divide a coleta entre vários frames; desligado, a thread principal fica parada enquanto o heap inteiro é verificado, o que pode chegar a centenas de ms - [Scripting.GarbageCollector.CollectIncremental](https://docs.unity3d.com/ScriptReference/Scripting.GarbageCollector.CollectIncremental.html) · Unity · A meta padrão de tempo por etapa do GC incremental (fatia de tempo) é de 3 ms (incrementalTimeSliceNanoseconds) - [Garbage Collection Settings in the Unreal Engine Project Settings](https://dev.epicgames.com/documentation/en-us/unreal-engine/garbage-collection-settings-in-the-unreal-engine-project-settings) · Epic Games · Configuração que faz o GC do Unreal rodar em um intervalo definido (Time Between Purging Pending Kill Objects, em segundos). O valor padrão não aparece neste documento - [Profiler markers reference](https://docs.unity3d.com/Manual/profiler-markers.html) · Unity · GC.Collect: trecho em que o código do programa fica parado durante a coleta de lixo (de menos de 1 ms a centenas de ms); GC.Alloc: alocação no heap gerenciado - [Stat Commands in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/stat-commands-in-unreal-engine) · Epic Games · stat GC (estatísticas da coleta de lixo), stat Hitches (registra em log os frames que passam de t.HitchFrameTimeThreshold) #### cg-sync-load · Carregamento síncrono e compilação de shaders na thread principal · Synchronous asset load, shader compile O jogo para porque precisa ler arquivos e compilar shaders logo antes de desenhar uma área, um monstro ou um efeito que aparece pela primeira vez. - Por quê → Efeito → Na tela: Entrada em uma área nova; skill, equipamento ou monstro que aparece pela primeira vez → A thread principal espera a leitura de arquivos e a compilação de shaders → Só na primeira vez, a tela trava por 0,1–1 s; da segunda vez em diante, tudo normal - Sintomas: Travamento, Engasgos / Fatores: Paralisação - Quem: Só eu / Quando: Em movimento ou ao trocar de mapa, Ao fazer ações específicas - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Usar carregamento assíncrono e pré-carregamento (prewarming), compilar os shaders antes da hora na tela de carregamento ou na primeira execução, aproveitar as telas de carregamento. - Números de referência: Compilar um shader leva dezenas de ms, às vezes mais de 100 ms. Carregar texturas leva de dezenas a centenas de ms, conforme a velocidade do disco. - No gráfico: Pico logo após abrir ou manutenção (Número de picos de frame (logo após patch ou atualização de driver)) - Onde olhar: Gravar o mesmo trajeto duas vezes com o PresentMon e comparar a primeira visita com a segunda. Em build de desenvolvimento, no Unreal, ativar r.PSOPrecache.Validation e verificar stat PSOPrecache e “PSO PRECACHING MISS” no log; no Unity, os trechos de carregamento e de shader dos frames com pico na Timeline do Profiler - Confirma se: Picos de 0,1–1 s só em lugares visitados ou skills usadas pela primeira vez, que somem na segunda vez. Os reports se concentram logo após um patch ou uma atualização do driver de vídeo e depois diminuem - Descarta se: Pico toda vez no mesmo lugar: descarta problema de cache de shaders. Se só se repete a cada deslocamento e apenas em PCs com disco lento: “Streaming de assets atrasado por disco lento”; se a memória dedicada da GPU está cheia: “Falta de memória de vídeo (VRAM)” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: No PC, o driver de vídeo guarda no cache de shaders cada shader já compilado e o reutiliza depois. Por isso, logo após uma atualização do driver de vídeo ou um patch do jogo, esse cache é invalidado, e até quem não tinha problema volta a ter engasgos por um tempo. O report típico é “depois do patch, dá um engasgo em todo lugar que visito pela primeira vez”. - Fontes: - [Shader loading](https://docs.unity3d.com/Manual/shader-loading.html) · Unity · Na primeira vez que uma variante de shader é usada, o driver de vídeo precisa prepará-la para a GPU, o que pode causar uma pausa visível; depois de pronta, ela fica em cache e não causa nova pausa - [Optimizing Rendering With PSO Caches in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/optimizing-rendering-with-pso-caches-in-unreal-engine) · Epic Games · Criar o estado de pipeline (PSO) no momento em que ele é necessário pode levar mais de 100 ms, por isso é preciso criá-lo antes - [Direct3D 12 Return Codes](https://learn.microsoft.com/en-us/windows/win32/direct3d12/d3d12-graphics-reference-returnvalues) · Microsoft · D3D12_ERROR_DRIVER_VERSION_MISMATCH: um cache de PSO criado com outra versão do driver não pode ser reutilizado (recompilação após atualizar o driver) - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Grava o tempo de cada frame com o FrameTime (tempo de CPU entre frames) - [PSO Precaching for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/pso-precaching-for-unreal-engine) · Epic Games · Com r.PSOPrecache.Validation ativado, stat PSOPrecache mostra estatísticas dos PSOs que escaparam do pré-cache e o log registra “PSO PRECACHING MISS”; criar um PSO em tempo de execução por mais de 20 ms (padrão) conta como hitch #### cg-asset-stream · Streaming de assets atrasado por disco lento · Slow storage stalls asset streaming Em armazenamento lento, como um HDD, a leitura de texturas e modelos de um mundo aberto não acompanha o deslocamento do personagem: entidades aparecem tarde ou o jogo engasga esperando a leitura. - Por quê → Efeito → Na tela: Deslocamento rápido com montaria ou teletransporte, ou entrada em um lugar cheio de gente, exige muitas texturas e modelos novos de uma vez → Um armazenamento lento como o HDD não lê na velocidade necessária, as leituras se acumulam na fila e alguns carregamentos fazem a thread principal esperar até o fim → Texturas borradas por um tempo, prédios e personagens aparecendo tarde, e engasgos ou travamentos nos momentos em que o jogo espera a leitura - Sintomas: Invisível / entidade fantasma, Engasgos, Travamento / Fatores: Paralisação - Quem: Só eu / Quando: Em movimento ou ao trocar de mapa, Quando junta muita gente - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de desenvolvimento): Usar streaming assíncrono que não faça a thread principal esperar a leitura, pré-carregar conforme a direção e a velocidade do deslocamento, mostrar primeiro versões de baixa resolução (mipmaps) e modelos simples e trocar depois, limitar por um instante a velocidade de deslocamento ou usar uma tela de carregamento quando o streaming atrasar em deslocamentos rápidos, informar nos requisitos mínimos e recomendados se o SSD é obrigatório. - O que fazer (Externo): Orientar os jogadores a instalar o jogo em um SSD e a verificar se há downloads ou varreduras de antivírus rodando no mesmo disco. - Números de referência: Segundo a Microsoft, discos rígidos antigos leem dezenas de MB por segundo e SSDs NVMe leem vários GB por segundo; jogos da geração anterior usavam cerca de 50 MB por segundo para streaming. Um jogo pensado para a velocidade de um SSD, que lê muito mais que isso, tende a não acompanhar o deslocamento quando roda em HDD. - No gráfico: Alto só em alguns (Número de picos de frame (por tipo de armazenamento), latência de leitura do disco) - Onde olhar: Registrar juntos, durante deslocamentos rápidos, PhysicalDisk\Avg. Disk sec/Read (tempo médio de uma leitura) e Current Disk Queue Length do Monitor de Desempenho do Windows e o frame time do PresentMon. Em build de desenvolvimento, stat Streaming e stat AsyncLoad no Unreal, e o aviso AssetBundle.asset/allAssets no Profiler do Unity (o resultado foi pedido antes de o carregamento terminar e a thread principal ficou esperando) - Confirma se: Em deslocamentos rápidos, a latência de leitura e a fila do disco disparam e, no mesmo momento, há picos de frame ou texturas e entidades aparecem tarde. A mesma cena rodando em SSD não tem o problema - Descarta se: Disco ocioso e texturas borradas: “Falta de memória de vídeo (VRAM)”. Normal a partir da segunda visita ao mesmo lugar: “Carregamento síncrono e compilação de shaders na thread principal” - Como verificar: Verificação no ambiente do jogador - Saiba mais: Se o jogo trava só na primeira vez e depois fica normal, o caso está mais para “Carregamento síncrono e compilação de shaders na thread principal”; se o problema se repete a cada deslocamento e só em PCs com armazenamento lento, é esta causa. A “Falta de memória de vídeo (VRAM)”, em que texturas são descarregadas e recarregadas porque a memória de vídeo não basta, também deixa texturas borradas, então verifique a espera de leitura do disco junto com o uso de memória de vídeo. A verificação em tempo real do antivírus também pode entrar no meio toda vez que o jogo abre um arquivo e atrasar ainda mais a leitura. - Fontes: - [DirectStorage is coming to PC](https://devblogs.microsoft.com/directx/directstorage-is-coming-to-pc/) · Microsoft · Discos rígidos antigos leem dezenas de MB por segundo e SSDs NVMe, vários GB por segundo; o orçamento de streaming de assets dos jogos da geração anterior era de cerca de 50 MB por segundo; jogos de mundo aberto leem e descartam a paisagem distante em tempo real durante o deslocamento - [Texture and mesh loading](https://docs.unity3d.com/Manual/LoadingTextureandMeshData.html) · Unity · O upload síncrono lê e envia os dados em um único frame na thread principal e causa uma pausa visível; o upload assíncrono faz o streaming ao longo de vários frames - [Texture Streaming Overview for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/texture-streaming-overview-for-unreal-engine) · Epic Games · O streamer aumenta e reduz a resolução das texturas (mips) conforme o ponto de vista, faz a maior parte do cálculo em threads de trabalho assíncronas e carrega primeiro os mips visíveis na tela - [Profiler markers reference](https://docs.unity3d.com/Manual/profiler-markers.html) · Unity · Aviso AssetBundle.asset/allAssets: o resultado foi pedido antes de o carregamento terminar, e a thread principal parou para esperar - [Stat Commands in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/stat-commands-in-unreal-engine) · Epic Games · stat Streaming (memória e quantidade de texturas em streaming), stat AsyncLoad (estatísticas de carregamento assíncrono) - [Windows Performance Monitor Disk Counters Explained](https://learn.microsoft.com/en-us/archive/blogs/askcore/windows-performance-monitor-disk-counters-explained) · Microsoft · Avg. Disk sec/Read é o tempo médio para concluir uma leitura (latência de I/O); Current Disk Queue Length é o tamanho da fila do disco no momento da medição - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Grava o tempo de cada frame com o FrameTime (tempo de CPU entre frames) - [About regular quick and full scans with Microsoft Defender Antivirus](https://learn.microsoft.com/en-us/defender-endpoint/schedule-antivirus-scans) · Microsoft · A proteção em tempo real verifica os arquivos toda vez que eles são abertos e fechados #### cg-crowd · Carga de renderização com muitos personagens · Render/animation cost of crowds Quando centenas de jogadores aparecem na mesma tela, como em guerras de castelo ou world bosses, o custo de desenhar tudo passa do que o aparelho aguenta. - Por quê → Efeito → Na tela: Centenas de personagens e efeitos se sobrepõem na mesma tela → O custo de animações, sombras, nomes acima dos personagens e efeitos cresce com o número de jogadores → O FPS cai (60 → 15), todos os movimentos engasgam e os comandos também respondem com atraso - Sintomas: Engasgos, Input lag / Fatores: Paralisação - Quem: Local ou canal específico, Só eu / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Usar simplificação por distância (LOD), limitar o número de personagens exibidos, oferecer opção de efeitos simplificados, reduzir a frequência de atualização das animações. - Números de referência: Mesmo com 0,02–0,1 ms por personagem, 300 personagens somam 6–30 ms. O orçamento do frame a 60 FPS é de 16,7 ms, então só isso já consome mais de 1/3 dele e, no pior caso, estoura. - No gráfico: Sobe com a carga (Frame time, número de personagens na tela) - Onde olhar: Comparar o frame time e o CPUBusy/GPUBusy do PresentMon antes e depois de uma guerra de castelo ou world boss. Em build de desenvolvimento, stat Unit no Unreal (tempo da game thread, da render thread e da GPU) - Confirma se: O frame time sobe junto com o número de personagens na tela e melhora na hora ao ativar o limite de personagens exibidos ou a opção de efeitos simplificados - Descarta se: Picos sem relação com o número de jogadores: “Picos de frame time” ou “Coleta de lixo (GC) no cliente”. FPS normal, mas só o movimento dos outros atrasa: “Gargalo no processamento de pacotes na thread principal” - Como verificar: Verificação no ambiente do jogador - Fontes: - [Introduction to level of detail](https://docs.unity3d.com/Manual/LevelOfDetail.html) · Unity · Sem LOD, objetos que aparecem pequenos na tela são desenhados com a mesma complexidade; o LOD reduz o custo de renderização - [Animation Budget Allocator in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/animation-budget-allocator-in-unreal-engine) · Epic Games · Reduz dinamicamente a atualização (tick) das animações de skeletal meshes para manter o tempo gasto com animação dentro do orçamento - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Com FrameTime, CPUBusy e GPUBusy, dá para saber se é a CPU ou a GPU que atrasa o frame - [Stat Commands in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/stat-commands-in-unreal-engine) · Epic Games · stat Unit: frame time total e tempo da game thread, da render thread e da GPU #### cg-net-mainthread · Gargalo no processamento de pacotes na thread principal · Network processing on the main thread Se o cliente processa só uma quantidade fixa de pacotes recebidos por frame, os pacotes que chegam em massa vão sendo empurrados para os frames seguintes. - Por quê → Efeito → Na tela: Em lugares cheios, chegam milhares de atualizações por segundo → A thread principal bate no limite de processamento por frame e não consegue ler tudo → Os movimentos dos outros jogadores chegam cada vez mais atrasados e são aplicados de uma vez só - Sintomas: Avanço rápido, Input lag / Fatores: Paralisação, Latência - Quem: Local ou canal específico, Só eu / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: fazer a recepção e o parsing em uma thread separada, juntar as atualizações de posição antigas da mesma entidade e aplicar só a mais recente. Servidor: em lugares cheios, enviar com menos frequência as atualizações de personagens distantes para reduzir o volume enviado. - Números de referência: Com pacotes não processados se acumulando, em poucos segundos o atraso já chega a 1 segundo inteiro de dados. - No gráfico: Sobe com a carga (Pacotes recebidos não processados, atraso entre recepção e aplicação) - Onde olhar: Registrar em log quantos pacotes o cliente deixa sem processar a cada frame e o atraso entre a chegada de um pacote e sua aplicação no jogo, junto com o número de jogadores ao redor - Confirma se: Em lugares cheios, o número de pacotes pendentes e o atraso de aplicação crescem sem parar, enquanto o ping e o intervalo de envio do servidor seguem normais no mesmo momento - Descarta se: Sem atraso de aplicação, mas com os pacotes já chegando atrasados: aponta para o trecho de rede. Frame time sobe muito: “Carga de renderização com muitos personagens” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Actor Priority in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-priority-in-unreal-engine) · Epic Games · Quando falta largura de banda, nem todos os atores são replicados toda vez; a prioridade é dada pela distância até quem está vendo e pelo tempo desde a última replicação - [Replication Graph in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/replication-graph-in-unreal-engine) · Epic Games · Jogos com muitos jogadores conectados e muitos objetos replicados (MMORPGs, por exemplo) precisam agrupar por posição e enviar só o necessário para evitar gargalo de CPU no servidor #### cg-no-buffer · Buffer de interpolação ausente ou curto demais · Missing/short interpolation buffer Se o cliente desenha os pacotes do servidor assim que chegam, o jitter (variação no intervalo de chegada dos pacotes) aparece direto na tela. - Por quê → Efeito → Na tela: A posição recebida é desenhada na hora, ou o buffer é menor que o jitter → A imagem para quando um pacote chega atrasado e pula quando vários chegam juntos → Os outros personagens se movem engasgando: para, anda, para - Sintomas: Engasgos / Fatores: Jitter - Quem: Só eu / Quando: Sempre - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: ter um buffer de interpolação e ajustar o tamanho dele automaticamente conforme o estado da conexão. Servidor: aplicar compensação de lag (voltar no tempo para decidir o acerto), para que o registro de acerto funcione mesmo quando o jogador atira em uma imagem atrasada pelo tamanho do buffer. - Números de referência: Em geral, o buffer fica em cerca de 2 vezes o intervalo de envio de pacotes do servidor (100 ms se o cliente recebe 20 pacotes por segundo). - No gráfico: Sempre alto desde o início (Intervalo de chegada dos pacotes, vezes em que o buffer de interpolação esvaziou) - Onde olhar: Registrar no cliente a distribuição dos intervalos de chegada dos pacotes do servidor e o número de frames em que a interpolação parou ou passou para extrapolação por falta do próximo snapshot - Confirma se: A variação no intervalo de chegada passa com frequência do tamanho do buffer de interpolação e, a cada vez, o buffer esvazia e os outros personagens dão um engasgo. Aumentar o buffer reduz o problema - Descarta se: Engasgos mesmo com buffer suficiente: verificar se o próprio intervalo de envio do servidor está irregular (atraso no tick) - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Um buffer maior deixa o movimento mais suave, mas faz você ver o adversário no passado na mesma proporção. Por isso, junto com ele se usa a compensação de lag: para decidir um ataque, o servidor volta no tempo até o “passado que aquele jogador estava vendo” e confere o acerto. - Fontes: - [Interpolation and extrapolation (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/interpolation.html) · Unity · Interpolação com buffer: desenhar com atraso proposital para esperar os pacotes atrasados; quanto maior o buffer, mais preciso, mas a latência cresce na mesma medida - [Struct ClientTickRate (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/api/Unity.NetCode.ClientTickRate.html) · Unity · Valor padrão do buffer de interpolação: InterpolationTimeNetTicks = 2 (o equivalente a 2 envios do servidor) - [Physics (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/physics.html) · Unity · Compensação de lag: o servidor reconstrói o mundo de colisão que o cliente via naquele tick e decide se houve acerto #### cg-extrap · Extrapolação excessiva (dead reckoning) · Over-extrapolation / dead reckoning Enquanto os pacotes não chegam, o cliente continua mostrando o personagem andando na última velocidade conhecida e, quando percebe o erro, puxa de volta. - Por quê → Efeito → Na tela: A recepção de pacotes para, e o cliente continua movendo o personagem na última direção e velocidade → Na verdade, o outro jogador parou ou mudou de direção → O personagem do outro anda um bom trecho e depois teleporta para a posição real, ou atravessa paredes. Com intervalos de chegada irregulares, ele avança e é puxado de volta várias vezes e parece tremer - Sintomas: Teleporte, Engasgos / Fatores: Perda de pacotes, Jitter - Quem: Só eu / Quando: Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Limitar o tempo de extrapolação (ex.: 200–250 ms), convergir suavemente para a posição certa quando a estimativa errar. - Números de referência: A 6 m/s, basta um erro de 300 ms para a posição ficar 1,8 m fora do lugar. - No gráfico: Picos aleatórios (Tempo de extrapolação, distância de correção da posição) - Onde olhar: Registrar por quanto tempo outros personagens foram desenhados por extrapolação e a distância corrigida na posição quando chegou o pacote novo - Confirma se: Em cada trecho sem pacotes, o tempo de extrapolação cresce sem limite e, depois, a distância corrigida chega a vários metros - Descarta se: Extrapolação curta e limitada, mas ainda com teleporte: a perda de pacotes ou a latência em si está alta; verifique a conexão e a rota - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Interpolation and extrapolation (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/interpolation.html) · Unity · Se o próximo snapshot não chega a tempo, a extrapolação, que continua movendo na mesma direção e velocidade, erra com frequência, por isso tem um limite (padrão do Unity: 20 ticks, cerca de 1/3 s a 60 Hz) - [Peeking into VALORANT's Netcode](https://technology.riotgames.com/news/peeking-valorants-netcode) · Riot Games · Quando a estimativa usada para cobrir dados atrasados ou perdidos erra, o cliente diverge do servidor, e o personagem pula ou desliza durante a correção #### cg-predict · Divergência na predição do cliente · Prediction mismatch / reconciliation Seu cliente mostra o movimento antes da confirmação; se o servidor calcular de outro jeito, seu personagem é puxado. - Por quê → Efeito → Na tela: O cliente move o personagem antes da confirmação do servidor (predição) → O servidor calcula colisão, velocidade de movimento ou buffs de outro jeito, ou não recebe o comando → Quando a confirmação chega, seu personagem é puxado para trás - Sintomas: Rubber banding / Fatores: Perda de pacotes, Latência - Quem: Só eu / Quando: Em movimento ou ao trocar de mapa, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: usar o mesmo código de movimento do servidor, enviar os inputs em duplicidade, corrigir de forma suave. Servidor: usar o mesmo código de movimento do cliente, descartar pelo número do input os inputs que chegam duplicados e processar cada um só uma vez. - Números de referência: A distância do puxão é “tempo de divergência × velocidade de movimento”. Basta perder alguns comandos para dar 1–3 m. - No gráfico: Picos aleatórios (Número de reconciliações com o servidor (falhas de predição)) - Onde olhar: Registrar quantas correções de posição o servidor enviou e a distância corrigida. No Unreal, as correções ClientAdjustPosition do servidor; no Unity Netcode for Entities, quantas vezes a predição falhou e foi revertida e recalculada - Confirma se: As correções se concentram nos horários dos reports de rubber banding, e correções grandes se repetem com certos buffs, terrenos ou skills de movimento - Descarta se: Correções concentradas só nos momentos de muita perda: aponta para perda dos pacotes de input (conexão). Sem correções, mas com outros personagens parecendo puxados: “Extrapolação excessiva (dead reckoning)” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Introduction to prediction (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/intro-to-prediction.html) · Unity · Cliente e servidor fazem a predição com o mesmo código de simulação; se o resultado diverge do estado do servidor (falha de predição), o cliente reverte e recalcula, e a correção fica visível - [Use the command stream to handle user inputs (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/command-stream.html) · Unity · Para cobrir a perda de pacotes, o input mais recente é enviado junto com os inputs dos últimos ticks, em duplicidade - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · O cliente se move primeiro e o servidor reproduz o mesmo movimento; se a posição diverge, corrige com ClientAdjustPosition e reaplica os movimentos salvos #### cg-fixed-step · Espiral de recuperação do timestep fixo · Fixed-timestep catch-up / spiral of death Depois de uma parada, o jogo tenta fazer de uma vez os cálculos atrasados e, por causa desse cálculo, atrasa de novo. - Por quê → Efeito → Na tela: A simulação do jogo roda em intervalos fixos e, em algum momento, para → Os passos atrasados são calculados todos em um só frame → Uma sequência de frames longos causa picos ou, ao bater no limite, o jogo entra em câmera lenta - Sintomas: Engasgos, Avanço rápido, Câmera lenta / Fatores: Paralisação - Quem: Só eu / Quando: Aleatoriamente, de vez em quando, Quando junta muita gente - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Limitar a recuperação por frame, tratar o tempo que sobra com interpolação. - No gráfico: Picos aleatórios (Frame time, passos fixos por frame) - Onde olhar: Ver no profiler da build de desenvolvimento quantas vezes o passo fixo rodou em um frame (no Unity, o número de marcadores da fase FixedUpdate, como FixedBehaviourUpdate) junto com o frame time - Confirma se: Depois de um frame longo vem uma sequência de frames longos que rodam vários passos e, ao bater no limite (Maximum Allowed Timestep no Unity), o tempo do jogo passa mais devagar que o real - Descarta se: Frame longo isolado, que não se repete: “Picos de frame time” ou “Coleta de lixo (GC) no cliente” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: A física do Unity (FixedUpdate) é o exemplo típico de passo fixo (0,02 s por padrão, 50 vezes por segundo). O Maximum Allowed Timestep das configurações de Time (o tempo máximo que um frame pode recuperar, cerca de 0,33 s por padrão) é o limite de recuperação. Se um frame passar disso, o tempo excedente é descartado, e o relógio do jogo fica atrasado em relação ao tempo real na mesma medida. - Fontes: - [Set fixed timestep to optimize physics simulation frequency](https://docs.unity3d.com/Manual/physics-optimization-cpu-frequency.html) · Unity · Fixed Timestep padrão de 0,02 s (50 vezes por segundo); com frames longos, a física roda vários passos em um frame e a carga aumenta - [Handling variation in time](https://docs.unity3d.com/Manual/time-handling-variations.html) · Unity · Maximum Allowed Timestep padrão de 1/3 s (0,3333333): mesmo com 1 s de parada, o tempo do jogo avança só 0,333 s; é o limite que impede o ciclo vicioso em que os passos de recuperação deixam tudo ainda mais lento - [Profiler markers reference](https://docs.unity3d.com/Manual/profiler-markers.html) · Unity · FixedBehaviourUpdate: trecho de execução de MonoBehaviour.FixedUpdate; os marcadores de física são chamados na fase FixedUpdate #### cg-clock · Erro na sincronização do relógio · Clock sync error Se a hora do servidor estimada pelo cliente estiver errada, o momento da interpolação e a decisão sobre o cooldown ficam desalinhados com o servidor. - Por quê → Efeito → Na tela: A hora do servidor é ajustada uma única vez, na conexão, e fica assim mesmo quando o ping muda → O momento da interpolação e a hora em que o cooldown termina ficam desalinhados com o servidor → O adversário dá um engasgo de vez em quando; o cooldown acabou, mas o servidor recusa a skill - Sintomas: Engasgos, Ação perdida / rollback / Fatores: Latência - Quem: Só eu / Quando: Quanto mais tempo ligado, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Sincronizar o horário periodicamente (medir o tempo de ida e volta e corrigir), fazer o ajuste aos poucos (sem saltos bruscos), medir o tempo decorrido com um monotonic clock, que não depende da hora do PC. - No gráfico: Subida lenta (Erro da hora estimada do servidor) - Onde olhar: Registrar periodicamente a diferença entre a hora do servidor estimada pelo cliente e a hora do servidor (número do tick) que vem nos pacotes - Confirma se: O erro cresce conforme passa o tempo desde a conexão, ou dá um salto de uma vez no instante em que o relógio do PC é acertado, e nessa mesma época aumentam os reports de skill recusada e de engasgos - Descarta se: Erro pequeno e estável, mas skills ainda recusadas: aponta para a decisão do servidor ou para a latência - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Se o tempo decorrido for medido pela data e hora do PC (wall clock), a hora do jogo dá um salto quando o Windows acerta o relógio pela hora da internet ou quando o jogador muda o relógio. O tempo decorrido precisa ser medido com um monotonic clock, que nunca anda para trás (Stopwatch, por exemplo). - Fontes: - [RFC 5905: Network Time Protocol Version 4: Protocol and Algorithms Specification](https://www.rfc-editor.org/rfc/rfc5905) · IETF · Método que calcula a latência de ida e volta e o erro do relógio a partir dos quatro instantes da requisição e da resposta - [Acquiring high-resolution time stamps](https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps) · Microsoft · QueryPerformanceCounter (usado pelo Stopwatch) é um relógio para tempo decorrido que não se sincroniza com uma hora externa; a hora do sistema só deve ser usada quando se precisa da hora UTC - [Time synchronization (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/time-synchronization.html) · Unity · Estima a hora do servidor pelo tempo de ida e volta e, sem mudar a hora de forma brusca, ajusta aos poucos a velocidade com que o tempo avança #### cg-float-time · Perda de precisão do tempo em float · Float time precision loss on long sessions Se a hora do jogo fica guardada em um formato decimal de baixa precisão (float), quanto mais tempo o jogo fica aberto, pior fica a resolução temporal (a menor diferença de tempo que dá para distinguir), e movimentos e efeitos começam a tremer. - Por quê → Efeito → Na tela: O tempo desde que o jogo foi aberto é acumulado em float ou passado assim mesmo para os shaders → Quanto mais tempo o jogo fica aberto, maior fica a menor diferença que o float consegue representar → Só no cliente aberto há dias, personagens, animações e efeitos com movimento tremem; reiniciando, tudo volta ao normal - Sintomas: Engasgos / Fatores: Jitter - Quem: Só eu / Quando: Quanto mais tempo ligado - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Guardar o tempo decorrido em double (64 bits) ou em inteiro, fazer o tempo passado aos shaders voltar a zero periodicamente, fazer testes automatizados de longa duração, de vários dias. - Números de referência: Um float de 32 bits tem pouco mais de 7 dígitos significativos; com o jogo aberto há um dia (cerca de 86.400 s), a resolução temporal fica em torno de 8 ms, cerca de metade de um frame a 60 FPS (16,7 ms), e, em uma semana, em torno de 60 ms, mais que um frame inteiro. - No gráfico: Subida lenta (Reports de tremor, por tempo de cliente aberto) - Onde olhar: Pedir, junto com cada report de tremor, há quanto tempo o cliente está aberto e comparar antes e depois de reiniciar. No desenvolvimento, testar com a hora de início do jogo ajustada para vários dias atrás - Confirma se: Treme só no cliente aberto há dias, some ao reiniciar e piora quanto mais tempo o jogo fica aberto - Descarta se: Treme logo depois de abrir: “Buffer de interpolação ausente ou curto demais” ou “Resolução do timer” - Como verificar: Verificação no ambiente do jogador - Saiba mais: Aparece principalmente em MMOs mobile em que o jogador deixa a caça automática ligada por dias sem fechar o jogo. O Time.time do Unity também é float, por isso o Unity oferece à parte o Time.timeAsDouble, em double, e recomenda usá-lo. - Fontes: - [Time.timeAsDouble](https://docs.unity3d.com/ScriptReference/Time-timeAsDouble.html) · Unity · Versão double de Time.time; com o jogo aberto por muito tempo, é mais precisa que float e, na maioria dos casos, é a recomendada - [Floating-point numeric types (C# reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types) · Microsoft · Precisão do float: cerca de 6–9 dígitos; double: cerca de 15–17 dígitos #### cg-vsync · V-Sync e fila de renderização · V-Sync, render queue O input lag aumenta enquanto alguns frames já desenhados pela GPU ficam em uma fila, esperando o ciclo do monitor para serem exibidos. - Por quê → Efeito → Na tela: O driver de vídeo acumula antecipadamente de 1 a 3 frames na fila → O comando leva esse tempo a mais para aparecer na tela → Ping baixo, mas o controle fica pesado e lento - Sintomas: Input lag, Engasgos / Fatores: Latência - Quem: Só eu / Quando: Sempre - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de desenvolvimento): Oferecer modo de baixa latência, reduzir a fila de frames, oferecer opção de limite de FPS um pouco abaixo da taxa de atualização, ativar o frame pacing no celular. - O que fazer (Externo): Orientar os jogadores a usar monitor com taxa de atualização variável e limite de FPS um pouco abaixo da taxa de atualização, e a ativar o modo de baixa latência do driver de vídeo. - Números de referência: A 60 Hz, cada frame vale 16,7 ms. Se a CPU for mais rápida que a GPU ou que o ciclo da tela e a fila de três frames (padrão do DirectX 11) encher, somam-se 50 ms. Com V-Sync de buffer duplo, um frame que levou 17 ms espera a próxima atualização da tela (33,3 ms), e nesse meio-tempo o frame anterior aparece mais uma vez. - No gráfico: Sempre alto desde o início (Latência do input até a tela) - Onde olhar: Comparar no PresentMon MsClickToPhotonLatency e MsAllInputToPhotonLatency (do input de mouse e teclado até o envio para a tela) e DisplayLatency, alternando V-Sync, modo de baixa latência e limite de FPS. MsPCLatency (do momento em que o PC recebe o input até o envio para a tela) só é registrado quando o jogo emite eventos de PC Latency - Confirma se: Com V-Sync ligado ou sem limite de FPS, essa latência aumenta em um ou dois frames (dezenas de ms) e diminui com o modo de baixa latência ou com limite de FPS um pouco abaixo da taxa de atualização. O ping não muda - Descarta se: Latência dentro do PC baixa, mas comandos ainda lentos: “Latência da tela, do dispositivo de entrada e da geração de frames”. Ping alto: aponta para a rede - Como verificar: Verificação no ambiente do jogador - Saiba mais: O V-Sync (sincronização vertical) é a configuração que só envia um frame novo no instante em que o monitor troca a imagem. O tearing some, mas os comandos atrasam pelo tempo de espera desse instante e, quando o FPS cai abaixo de 60, ele alterna entre 60 e 30 e a imagem engasga. Monitores com taxa de atualização variável trocam a imagem quando o frame fica pronto e reduzem essa espera. O mesmo acontece no celular. Se um jogo de 30 FPS não consegue entregar os frames de forma regular a uma tela de 60 Hz, a média fica em 30 FPS, mas cada frame fica na tela por tempos irregulares, como 49 ms, 16 ms e 33 ms, e a imagem engasga (exemplo da documentação para desenvolvedores Android). A biblioteca de frame pacing do Android (que regulariza o intervalo de saída dos frames), ou a opção equivalente da engine, reduz o problema. - Fontes: - [IDXGIDevice1::SetMaximumFrameLatency](https://learn.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgidevice1-setmaximumframelatency) · Microsoft · Número padrão de frames que o driver pode acumular na fila: 3 (de 1 a 16) - [Reduce latency with DXGI 1.3 swap chains](https://learn.microsoft.com/en-us/windows/uwp/gaming/reduce-latency-with-dxgi-1-3-swap-chains) · Microsoft · O Present fica bloqueado até a fila esvaziar, então, depois de desenhado, o frame espera quase um frame inteiro a mais até ser exibido; uma swap chain com espera (waitable) reduz isso - [Frame Pacing library](https://developer.android.com/games/sdk/frame-pacing) · Android (Google) · Em uma tela de 60 Hz, sem frame novo, o anterior é exibido de novo; exemplo de um jogo de 30 FPS com frame times irregulares de 49 ms, 16 ms e 33 ms - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · MsPCLatency (do momento em que o PC recebe o input até o envio para a tela), MsClickToPhotonLatency (do clique do mouse até a tela), MsAllInputToPhotonLatency (do input de teclado ou mouse até a tela), DisplayLatency (do envio do frame até a saída para o monitor) - [PresentMon Console Application (README-ConsoleApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-ConsoleApplication.md) · Intel · MsPCLatency só é registrado se o app emitir eventos de PC Latency (--track_pc_latency); MsAllInputToPhotonLatency considera o input de teclado e mouse #### cg-leak · Vazamento de memória no cliente · Client memory leak Quanto mais tempo o jogo fica aberto, mais memória ele usa; vai ficando lento e, no fim, é fechado à força. - Por quê → Efeito → Na tela: Texturas, UI e efeitos não são liberados nas trocas de mapa → O GC roda com mais frequência e, com pouca memória no SO, começa o swap → Depois de algumas horas de jogo, os engasgos vão aumentando até o encerramento forçado (para o jogador, parece uma desconexão) - Sintomas: Engasgos, Desconexão / Fatores: Paralisação - Quem: Só eu / Quando: Quanto mais tempo ligado - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Medir o uso de memória nas trocas de mapa, encontrar e corrigir texturas, UI e efeitos que não são liberados, fazer testes automatizados de longa duração (soak tests). - No gráfico: Subida lenta (Memória do processo do jogo) - Onde olhar: Registrar Process(jogo)\Private Bytes no Monitor de Desempenho por algumas horas. No mobile, o motivo de encerramento no ApplicationExitInfo do Android (REASON_LOW_MEMORY) e os relatórios de jetsam do iOS - Confirma se: A memória sobe a cada troca de mapa e não volta a cair, e engasgos e encerramentos forçados aumentam quanto mais tempo o jogo fica aberto - Descarta se: Memória estável, e só o tremor piora quanto mais tempo o jogo fica aberto: “Perda de precisão do tempo em float” - Como verificar: Verificação no ambiente do jogador - Saiba mais: Celulares costumam aguentar comprimindo a memória. Se mesmo assim faltar memória, o SO fecha o jogo na hora (o jogador cai do jogo). Quanto menos RAM o aparelho tem, mais cedo isso acontece. - Fontes: - [Memory allocation among processes](https://developer.android.com/topic/performance/memory-management) · Android (Google) · O Android aguenta comprimindo a memória em zRAM e, quando ela acaba, o low memory killer encerra processos; quando o app em primeiro plano é encerrado, parece um crash - [Identifying high-memory use with jetsam event reports](https://developer.apple.com/documentation/xcode/identifying-high-memory-use-with-jetsam-event-reports) · Apple · Se a pressão de memória não diminui, o iOS encerra apps à força (jetsam), e o app que passa do seu limite de memória vira candidato a ser encerrado - [Find user-mode memory leaks with Performance Monitor (PerfMon)](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/using-performance-monitor-to-find-a-user-mode-memory-leak) · Microsoft · Registrar por muito tempo Process > Private Bytes (memória privada alocada pelo processo) e Virtual Bytes; se só sobem, é vazamento - [ApplicationExitInfo](https://developer.android.com/reference/android/app/ApplicationExitInfo) · Android (Google) · REASON_LOW_MEMORY: o low memory killer do sistema encerrou o processo do app (aparelhos sem suporte informam REASON_SIGNALED com SIGKILL) #### cg-crash · Crash do cliente · Client crash Um erro não tratado fecha o jogo. Para o jogador, parece uma desconexão, mas o servidor está normal. - Por quê → Efeito → Na tela: Referência nula, falta de memória, erro do driver de vídeo → O processo do jogo é encerrado à força → Reports de “caí do jogo”, enquanto os outros jogadores seguem normais no mesmo horário - Sintomas: Desconexão / Fatores: Paralisação - Quem: Só eu / Quando: Ao fazer ações específicas, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de desenvolvimento): Coletar relatórios de crash, fazer estatísticas por aparelho e por driver, corrigir primeiro os erros mais frequentes. - O que fazer (Externo): Se os crashes se concentram em uma versão específica do driver de vídeo, orientar os jogadores a atualizar o driver. - No gráfico: Alto só em alguns (Número de crashes (por aparelho, driver de vídeo e build)) - Onde olhar: Relatórios de crash e taxa de crash do Android vitals por aparelho, driver e build. No PC do jogador, o evento com ID 1000 no log de Aplicativo do Visualizador de Eventos (nome do módulo com falha) e os registros “Display driver stopped responding and has recovered” - Confirma se: Há registro de crash no horário do report de desconexão, e os outros jogadores do mesmo servidor estão normais no mesmo horário. Os crashes se concentram em certos aparelhos, versões de driver ou módulos - Descarta se: Sem registro de crash, só a conexão caiu: “Expiração do mapeamento NAT” ou problema na conexão - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Crashes](https://developer.android.com/topic/performance/vitals/crash) · Android (Google) · Crash é o encerramento inesperado do app por uma exceção não tratada ou um sinal (SIGSEGV etc.), contabilizado no Android vitals do Play Console - [WDDM Support for Timeout Detection and Recovery (TDR)](https://learn.microsoft.com/en-us/windows-hardware/drivers/display/timeout-detection-and-recovery) · Microsoft · Se a GPU não termina um trabalho em 2 s (padrão), o Windows reinicia o driver de vídeo e a GPU - [The application or service crashing behavior troubleshooting guidance](https://learn.microsoft.com/en-us/troubleshoot/windows-server/performance/troubleshoot-application-service-crashing-behavior) · Microsoft · No log de Aplicativo, o evento com ID 1000 é o registro real do crash e traz o nome do aplicativo com falha e do módulo com falha (Faulting module name) #### cg-anticheat · Verificações do anti-cheat (módulo de segurança do jogo) · Anti-cheat scan and heartbeat Para impedir trapaças, um módulo de segurança roda junto com o jogo e faz verificações periódicas. Se a verificação for pesada ou se o heartbeat (sinal periódico de que o cliente está ativo) trocado com o servidor de segurança atrasar, o jogo engasga ou a conexão cai. - Por quê → Efeito → Na tela: O módulo de segurança verifica periodicamente a memória do jogo, os programas em execução e os drivers → Durante a verificação, a thread do jogo para ou o heartbeat não sai a tempo → Engasgos em intervalos regulares e, nos casos graves, desconexão com uma mensagem de erro de segurança - Sintomas: Engasgos, Travamento, Desconexão / Fatores: Paralisação - Quem: Só eu / Quando: Em intervalos regulares, Logo após login ou manutenção, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: rodar as verificações pesadas fora da thread do jogo, divididas em partes pequenas, comparar estatísticas de engasgos e quedas do jogo por versão do módulo de segurança (se aumentarem logo após uma atualização, repassar ao fornecedor do módulo). Servidor: tolerar um ou dois heartbeats atrasados. - Números de referência: Uma verificação leve costuma levar menos de 1 ms, mas uma verificação pesada que roda na thread do jogo pode ocupar de dezenas a centenas de ms por vez, dependendo da implementação. - No gráfico: Picos em intervalos regulares (Frame time, kicks do anti-cheat) - Onde olhar: Medir os intervalos dos picos no frame time do PresentMon e agregar, por versão do módulo de segurança e por configuração de hardware, os motivos de kick do anti-cheat recebidos pelo servidor (no EOS, AuthenticationFailed / Authentication Timed Out etc. em ClientActionReason) - Confirma se: Pausas curtas se repetem em intervalos regulares, sem relação com o que acontece no jogo, e, logo após uma atualização do módulo de segurança, engasgos e kicks por timeout de autenticação aumentam em certas configurações de hardware - Descarta se: Mesmo intervalo em todas as configurações, sem relação com a versão do módulo de segurança: “Coleta de lixo (GC) no cliente” ou “Processos em segundo plano ocupando a CPU” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: O módulo de segurança fica instalado no fundo do SO como driver e às vezes entra em conflito com antivírus, overlays ou o módulo de segurança de outros jogos. Se, logo após uma atualização do módulo, os reports de engasgos e quedas do jogo se concentrarem em certas configurações de hardware, ele é o primeiro suspeito. - Fontes: - [Using the Anti-Cheat Interfaces](https://dev.epicgames.com/docs/epic-online-services/trust-and-safety/anti-cheat-interfaces/using-anti-cheat) · Epic Games · Se o servidor não recebe a mensagem do anti-cheat do cliente dentro do tempo definido (RegisterTimeout), ele expulsa o cliente por timeout de autenticação (causa comum: cliente parado em um carregamento); se o problema vier de uma atualização recente do módulo, voltar para o módulo anterior - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Grava o tempo de cada frame com o FrameTime (tempo de CPU entre frames) ### L2 SO e dispositivo do cliente (15 causas) #### co-background · Processos em segundo plano ocupando a CPU · Background CPU contention Quando a varredura do antivírus, o Windows Update, um programa de transmissão ao vivo ou um vídeo no navegador ocupam os núcleos, a thread do jogo fica esperando, sem receber tempo de CPU. - Por quê → Efeito → Na tela: Outro programa ocupa um núcleo da CPU por muito tempo → A thread do jogo fica esperando CPU na fila do escalonador → Os frames atrasam, e o processamento dos pacotes recebidos também - Sintomas: Engasgos, Avanço rápido / Fatores: Paralisação - Quem: Só eu / Quando: Aleatoriamente, de vez em quando, Em intervalos regulares - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Ajustar a prioridade da thread do jogo, registrar o uso total de CPU do PC nos logs gerados quando há engasgos, para saber se a culpa é de outro programa. - O que fazer (Externo): Orientar os jogadores a ativar o Modo de Jogo do Windows e a fechar programas desnecessários durante o jogo (varredura do antivírus, Windows Update, programa de transmissão ao vivo, vídeo no navegador). - Números de referência: Em geral, o Windows entrega cada núcleo em fatias de alguns ms a dezenas de ms. Basta ficar para trás uma única vez no escalonamento para perder um frame. - No gráfico: Picos aleatórios (Uso total de CPU do PC, frame time) - Onde olhar: Registrar a coluna CPU da guia Processos do Gerenciador de Tarefas e Processor Information(_Total)\% Processor Time do Monitor de Desempenho junto com o frame time do PresentMon. Se o antivírus for suspeito, gravar com New-MpPerformanceRecording e ver com Get-MpPerformanceReport os arquivos e processos com maior tempo de verificação - Confirma se: No horário do engasgo, o uso de CPU de outro programa (varredura do antivírus, atualização, programa de transmissão) dispara, ou arquivos da pasta do jogo aparecem no topo do tempo de verificação. Ao fechar esse programa ou adicionar uma exclusão, o problema some - Descarta se: Uso de CPU baixo, mas a tela inteira engasga e o som chia: “Economia de energia e problemas de driver da placa de rede” (latência de DPC) - Como verificar: Verificação no ambiente do jogador - Saiba mais: O Windows dá um pouco mais de prioridade ao programa da janela em primeiro plano, mas, se houver mais trabalho do que núcleos, o jogo também espera. O antivírus interfere mais vezes pela “proteção em tempo real” do que pelo uso de CPU. Ele verifica cada arquivo que o jogo abre, e as pausas na leitura de assets ficam mais longas. - Fontes: - [Multitasking](https://learn.microsoft.com/en-us/windows/win32/procthread/multitasking) · Microsoft · O Windows dá a cada thread uma fatia de tempo e, quando ela acaba, passa para a próxima thread; a fatia de tempo é de cerca de 20 ms (varia conforme o SO e a CPU) - [Priority Boosts](https://learn.microsoft.com/en-us/windows/win32/procthread/priority-boosts) · Microsoft · O processo da janela em primeiro plano recebe prioridade igual ou maior que a dos processos em segundo plano - [About regular quick and full scans with Microsoft Defender Antivirus](https://learn.microsoft.com/en-us/defender-endpoint/schedule-antivirus-scans) · Microsoft · A proteção em tempo real verifica os arquivos toda vez que eles são abertos e fechados e toda vez que uma pasta é aberta - [Network-Related Performance Counters](https://learn.microsoft.com/en-us/windows-server/networking/technologies/network-subsystem/net-sub-performance-counters) · Microsoft · Contador Processor Information: % Processor Time - [Performance analyzer for Microsoft Defender Antivirus](https://learn.microsoft.com/en-us/defender-endpoint/tune-performance-defender-antivirus) · Microsoft · Gravar com New-MpPerformanceRecording e ver com Get-MpPerformanceReport os arquivos, caminhos e processos que mais pesaram no tempo de verificação - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Grava o tempo de cada frame com o FrameTime (tempo de CPU entre frames) #### co-power · Modo de economia de energia e thermal throttling · Power saving, thermal throttling No modo bateria do notebook, no modo de economia de energia do celular ou com o aparelho quente, a CPU e a GPU ficam mais lentas. O sinal típico do aquecimento é o jogo começar bem e ficar lento só depois de um bom tempo. - Por quê → Efeito → Na tela: Modo bateria ou de economia de energia ligado, ou aparelho esquentando → O clock da CPU e da GPU cai 30–50%, conforme o aparelho → Com economia de energia, logo de cara; com aquecimento, depois de alguns minutos a uns 20 minutos de jogo, o FPS cai e a imagem engasga - Sintomas: Engasgos, Input lag / Fatores: Paralisação - Quem: Só eu / Quando: Quanto mais tempo ligado, Sempre - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Ajustar automaticamente as opções gráficas, controlar o aquecimento com limite de FPS, baixar as opções antes da hora com base no nível térmico informado pelo SO (thermalState no iOS, API de estado térmico no Android), marcar o executável para usar a GPU dedicada em notebooks com dois chips gráficos (exportar NvOptimusEnablement e AmdPowerXpressRequestHighPerformance). - O que fazer (Externo): Orientar os jogadores a desligar o modo de economia de energia e a jogar com o notebook ligado na tomada; em reports de “notebook bom, mas FPS baixo”, verificar em qual chip gráfico o jogo está rodando e orientar o jogador a definir, nas configurações de gráficos do Windows, que o jogo use a GPU de alto desempenho. - No gráfico: Subida lenta (FPS, clock da CPU e da GPU) - Onde olhar: Registrar no PresentMon CPUFrequency, GPUFrequency, CPUTemperature e GPUTemperature junto com o frame time por 20–30 minutos e verificar, na coluna Mecanismo de GPU da guia Processos do Gerenciador de Tarefas, em qual chip gráfico o jogo está rodando. No mobile, registrar a API térmica do Android (getThermalHeadroom, estado térmico) e o thermalState do iOS junto com o FPS - Confirma se: A temperatura sobe, o clock cai e, a partir daí, o FPS cai junto, ou o clock só fica baixo no modo bateria ou de economia de energia. Ou o jogo está rodando na GPU integrada - Descarta se: Clock e temperatura estáveis, mas FPS caindo: “Processos em segundo plano ocupando a CPU” ou “Vazamento de memória no cliente” - Como verificar: Verificação no ambiente do jogador - Saiba mais: Notebooks com dois chips gráficos às vezes rodam o jogo na GPU integrada, mais lenta, para economizar energia. Em reports de “notebook bom, mas FPS baixo”, verifique primeiro em qual chip gráfico o jogo está rodando. - Fontes: - [Thermal API](https://developer.android.com/games/optimize/adpf/thermal) · Android (Google) · O aparelho mantém o alto desempenho só por tempo limitado e depois sofre throttling por aquecimento; recomenda-se reduzir a carga antes da hora, com base no estado térmico - [thermalState](https://developer.apple.com/documentation/foundation/processinfo/thermalstate-swift.property) · Apple · Nível térmico atual informado pelo iOS; quando o nível sobe, o app deve reduzir o uso de recursos - [Selecting the Best Graphics Device to Run a 3D Intensive Application](https://gpuopen.com/learn/amdpowerxpressrequesthighperformance/) · AMD · Em notebooks com dois chips gráficos, rodar na GPU integrada pode fazer um jogo de 60 FPS cair para 30 FPS; exportar AmdPowerXpressRequestHighPerformance seleciona a GPU dedicada - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Registra por frame CPUFrequency e GPUFrequency (clock) e CPUTemperature e GPUTemperature (temperatura) - [GPUs in the task manager](https://devblogs.microsoft.com/directx/gpus-in-the-task-manager/) · Microsoft · O Gerenciador de Tarefas tem colunas que mostram o uso de GPU por processo e a qual GPU e mecanismo esse valor pertence #### co-timer · Resolução do timer · Timer resolution (Windows 15.6ms) O timer padrão do Windows trabalha em passos de 15,6 ms, então um “espere só 1 ms” na prática vai até o próximo ciclo do timer, podendo chegar a 15,6 ms. - Por quê → Efeito → Na tela: Limitação de frames e envio de pacotes implementados com Sleep (espera curta) → O SO só acorda a thread em passos de 15,6 ms → Os intervalos entre frames e entre envios de input ficam irregulares - Sintomas: Engasgos / Fatores: Jitter - Quem: Só eu / Quando: Sempre - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Usar timer de alta resolução, fazer o pacing com base em eventos ou no V-Sync, sem depender de esperas com Sleep. - Números de referência: Com passos de 15,6 ms, não dá para acertar um intervalo de 16,7 ms, e o intervalo entre frames alterna entre 15,6 ms e 31,2 ms. - No gráfico: Sempre alto desde o início (Distribuição dos intervalos entre frames) - Onde olhar: Ver a distribuição de MsBetweenPresents (intervalo entre frames) no PresentMon e o item “Platform Timer Resolution” do relatório powercfg /energy (processos que mudaram a resolução do timer) - Confirma se: Os intervalos entre frames se concentram em múltiplos de 15,6 ms, como 15,6 ms e 31,2 ms, e o jogo não pede uma resolução de timer mais alta - Descarta se: Intervalos espalhados de forma uniforme: aponta mais para “Processos em segundo plano ocupando a CPU” ou para a carga do frame do que para o timer - Como verificar: Verificação no ambiente do jogador - Saiba mais: Nas versões antigas do Windows, quando um programa mudava o timer para 1 ms, a mudança valia para todos os programas. Por isso circulava até a dica “com o navegador aberto, o jogo fica mais suave”. A partir do Windows 10 versão 2004, a mudança vale só para o programa que a pediu, e o Windows 11 pode ignorar o pedido de janelas minimizadas ou totalmente encobertas que não estejam emitindo som. - Fontes: - [_WDF_TIMER_CONFIG (wdftimer.h)](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdftimer/ns-wdftimer-_wdf_timer_config) · Microsoft · A precisão dos timers comuns é o intervalo do tick do relógio do sistema, 15,6 ms por padrão; a dos timers de alta resolução é de 1 ms - [timeBeginPeriod function (timeapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod) · Microsoft · Antes do Windows 10 versão 2004, era uma configuração global; depois, vale só para o processo que pediu; o Windows 11 não garante a resolução alta para processos com janelas encobertas ou minimizadas - [CreateWaitableTimerExW function (synchapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createwaitabletimerexw) · Microsoft · Flag de timer de espera de alta resolução: CREATE_WAITABLE_TIMER_HIGH_RESOLUTION - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · MsBetweenPresents: tempo entre esta chamada de Present() e a anterior (ms) - [Results for the Idle Energy Efficiency Assessment](https://learn.microsoft.com/en-us/windows-hardware/test/assessments/results-for-the-idle-energy-efficiency-assessment) · Microsoft · Resolução padrão do timer do sistema: 15,6 ms; o item “Platform Timer Resolution” do relatório de energia mostra os processos que mudaram a resolução do timer - [Powercfg command-line options](https://learn.microsoft.com/en-us/windows-hardware/design/device-experiences/powercfg-command-line-options) · Microsoft · powercfg /energy: analisa o sistema e gera um relatório de energia (HTML) #### co-mobile-bg · App mobile em segundo plano · App suspended in background Se você tira o app da tela por um instante para ver uma notificação, o SO o suspende (suspend) alguns segundos depois e, nesse meio-tempo, o servidor desconecta você. - Por quê → Efeito → Na tela: O jogador sai do jogo para ver uma mensagem ou atender uma ligação → A engine pausa o jogo, e logo depois o SO também suspende o app e a rede → Ao voltar, a conexão já caiu; é preciso reconectar - Sintomas: Desconexão / Fatores: Paralisação, Perda de pacotes - Quem: Só eu / Quando: Depois de ficar parado, Ao fazer ações específicas - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: ao voltar, sem esperar pela conexão que caiu, reconectar automaticamente na hora com o token de sessão (retomar sem novo login) e receber o estado mais recente de uma vez para se sincronizar. Servidor: quando os heartbeats param, encerrar a conexão, mas manter a sessão do personagem por um curto tempo de tolerância (sem expulsar na hora) e, se o jogador reconectar nesse prazo, retomar pelo token de sessão. - Números de referência: Em geral, a engine pausa no instante em que o app sai da tela. O iOS suspende o app em alguns segundos e, mesmo com tempo extra concedido, geralmente em algumas dezenas de segundos; no Android 14 ou superior, o app que saiu da tela é congelado (freeze) depois de uns 10 segundos. - No gráfico: Queda de conexões em massa (Desconexões (timeout de heartbeat), registros de suspensão do app) - Onde olhar: Cruzar, pelo ID de sessão, os horários de suspensão e retorno do app no log do cliente (OnApplicationPause no Unity) com o motivo e o horário da desconexão no servidor. No Android, ver também o motivo de encerramento do processo registrado no ApplicationExitInfo (REASON_LOW_MEMORY etc.) - Confirma se: Logo antes da desconexão por timeout de heartbeat no servidor, o cliente entrou em suspensão e, logo depois de voltar, reconectou - Descarta se: Caiu com o app em primeiro plano: “Expiração do mapeamento NAT”, “IP compartilhado pela operadora (CGNAT)” ou “Troca Wi-Fi ↔ LTE/5G” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Quando falta memória, o celular às vezes encerra de vez o jogo que estava em segundo plano. É por isso que, depois de abrir a câmera ou um app de pagamento ou de autenticação, o jogo recomeça do zero. É mais comum em aparelhos mais fracos. - Fontes: - [Extending your app’s background execution time](https://developer.apple.com/documentation/uikit/extending-your-app-s-background-execution-time) · Apple · Ao ir para segundo plano, o app recebe 5 s em applicationDidEnterBackground e logo é suspenso; se precisar de mais, pede tempo com beginBackgroundTask (o tempo restante fica em backgroundTimeRemaining) - [Cached apps freezer](https://source.android.com/docs/core/perf/cached-apps-freezer) · Android (Google) · No Android 14 ou superior, processos de apps em estado de cache são congelados após 10 s e, uma vez congelados, todas as suas threads param - [Application.runInBackground](https://docs.unity3d.com/ScriptReference/Application-runInBackground.html) · Unity · Com o padrão false, o jogo pausa em segundo plano; no Android, pausa em segundo plano independentemente da configuração, e o iOS ignora essa configuração - [MonoBehaviour.OnApplicationPause(bool)](https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnApplicationPause.html) · Unity · Quando o app é suspenso ou volta a rodar, envia OnApplicationPause(true/false) para todos os MonoBehaviours - [ApplicationExitInfo](https://developer.android.com/reference/android/app/ApplicationExitInfo) · Android (Google) · REASON_LOW_MEMORY: o low memory killer do sistema encerrou o processo do app (aparelhos sem suporte informam REASON_SIGNALED com SIGKILL) #### co-netswitch · Troca Wi-Fi ↔ LTE/5G · Network switch changes IP Quando você sai de casa, o Wi-Fi cai e o celular passa para LTE/5G; seu endereço IP muda e a conexão existente deixa de valer. - Por quê → Efeito → Na tela: O sinal do Wi-Fi enfraquece e o celular passa para a rede móvel → Seu endereço IP muda, e a conexão aberta com o endereço antigo não consegue mais trocar dados → Uma pausa curta seguida de desconexão ou reconexão - Sintomas: Travamento, Desconexão / Fatores: Perda de pacotes - Quem: Só eu / Quando: Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Servidor: com o token de sessão, reconhecer o mesmo jogador mesmo com endereço novo e encerrar na hora a conexão do endereço antigo, avaliar protocolos que mantêm a conexão quando o endereço muda (como a migração de conexão do QUIC). Cliente: ao detectar a troca de rede, reconectar na hora com o token de sessão, sem esperar o timeout de heartbeat. - O que fazer (Equipe de infraestrutura): Ao usar a migração de conexão do QUIC, configurar o load balancer para escolher o servidor pelo ID de conexão, sem usar endereço e porta (se escolher por endereço e porta, os pacotes com endereço novo vão para outro servidor). - No gráfico: Queda de conexões em massa (Desconexões e reconexões, IP alterado na reconexão) - Onde olhar: Procurar nos logs de conexão do servidor reconexões do mesmo token de sessão com outro IP e cruzar com o horário do callback de mudança da rede padrão no cliente (registerDefaultNetworkCallback) - Confirma se: Logo depois da queda, o IP da reconexão muda da faixa do Wi-Fi (conexão de casa) para a faixa da operadora móvel, ou o contrário, e logo antes chega o callback de troca de rede - Descarta se: Caiu com o mesmo IP: “Handover entre antenas (em movimento)” ou “Sinal de celular fraco e áreas de sombra” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Read network state](https://developer.android.com/training/basics/network-ops/reading-network-state) · Android (Google) · Quando a rede padrão muda, novas conexões vão para a rede nova e as conexões da rede anterior acabam sendo derrubadas; a troca é detectada com registerDefaultNetworkCallback - [RFC 9000: QUIC: A UDP-Based Multiplexed and Secure Transport](https://www.rfc-editor.org/rfc/rfc9000) · IETF · Com o ID de conexão, a conexão se mantém mesmo quando o endereço IP e a porta mudam (seção 9); um load balancer que distribui só por endereço e porta pode mandar pacotes com endereço novo para outro servidor (seção 5.2.3) - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · Uma conexão TCP é identificada pelo par de sockets (endereço e porta) das duas pontas #### co-security · Inspeção de pacotes por software de segurança · Antivirus / firewall inspection Quando o antivírus ou o firewall inspeciona cada pacote, a latência aumenta e, se a inspeção for agressiva demais, ele toma o jogo por um ataque e o bloqueia. - Por quê → Efeito → Na tela: O software de segurança inspeciona um por um os pacotes enviados e recebidos → Cada pacote ganha um atraso e, quando a inspeção fica para trás, pacotes são descartados → Picos irregulares de ping ou conexão bloqueada - Sintomas: Engasgos, Não conecta / loading infinito / Fatores: Jitter, Perda de pacotes - Quem: Só eu / Quando: Sempre, Logo após login ou manutenção - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Manter uma lista de compatibilidade com softwares de segurança, registrar uma exceção para o jogo no Firewall do Windows durante a instalação. - O que fazer (Externo): Orientar os jogadores a adicionar o jogo como exceção no software de segurança e, se o jogo for tomado por ataque, pedir ao fornecedor do software a correção do falso positivo. - Números de referência: Em situação normal, a inspeção de um pacote costuma levar menos de 1 ms. O problema surge quando o módulo de inspeção fica para trás ou tem bug, ou quando ele toma o tráfego do jogo por um ataque. - No gráfico: Alto só em alguns (RTT e falhas de conexão (por jogador)) - Onde olhar: Comparar com o software de segurança desligado por um instante ou com o jogo adicionado como exceção. No Windows, ao ativar Audit Filtering Platform Connection e Audit Filtering Platform Packet Drop na política de auditoria, o log de Segurança registra os eventos 5157 (conexão bloqueada) e 5152 (pacote bloqueado), e WFPv4\Packets Discarded/sec, no Monitor de Desempenho, mostra o número de pacotes descartados - Confirma se: Há registros de bloqueio de conexões ou pacotes para o endereço do servidor do jogo, ou os picos de ping e as falhas de conexão somem ao desligar o software de segurança - Descarta se: Outros dispositivos da mesma casa têm o mesmo problema, sem relação com o software de segurança: aponta para o roteador ou a conexão - Como verificar: Verificação no ambiente do jogador - Fontes: - [About Windows Filtering Platform](https://learn.microsoft.com/en-us/windows/win32/fwp/about-windows-filtering-platform) · Microsoft · Arquitetura que permite ou bloqueia pacotes com hooks na pilha de rede do Windows e um mecanismo de filtragem; fornecedores de segurança externos podem inserir seus próprios módulos de filtro (callouts) - [Windows Firewall Rules](https://learn.microsoft.com/en-us/windows/security/operating-system-security/network-security/windows-firewall/rules) · Microsoft · Por padrão, conexões de entrada são bloqueadas, então o app precisa de uma regra de exceção, que costuma ser criada pelo instalador do app - [Address false positives/negatives in Microsoft Defender for Endpoint](https://learn.microsoft.com/en-us/defender-endpoint/defender-endpoint-false-positives-negatives) · Microsoft · Procedimento para configurar exceções e enviar o arquivo para análise da Microsoft quando um programa legítimo é tomado por ameaça (falso positivo) - [5157(F): The Windows Filtering Platform has blocked a connection.](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-5157) · Microsoft · Evento 5157: a Windows Filtering Platform bloqueou uma conexão (Audit Filtering Platform Connection) - [Audit Filtering Platform Packet Drop](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/audit-filtering-platform-packet-drop) · Microsoft · Evento 5152: a Windows Filtering Platform bloqueou um pacote - [Network-Related Performance Counters](https://learn.microsoft.com/en-us/windows-server/networking/technologies/network-subsystem/net-sub-performance-counters) · Microsoft · WFPv4 e WFPv6: contador Packets Discarded/sec #### co-rcvbuf · Estouro do buffer de recepção · Socket receive buffer overflow Se o jogo está ocupado e demora para tirar os pacotes do socket (a interface de envio e recepção de rede oferecida pelo SO), o buffer do SO estoura. - Por quê → Efeito → Na tela: Os frames atrasam e o jogo lê o socket tarde → O buffer de recepção do SO enche: o UDP descarta pacotes, e o TCP reduz a janela de recepção para parar o envio → Teleporte (UDP) ou avanço rápido (TCP) - Sintomas: Teleporte, Avanço rápido / Fatores: Perda de pacotes, Paralisação - Quem: Só eu / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Usar uma thread dedicada à recepção, ajustar o tamanho do buffer (SO_RCVBUF). - Números de referência: O buffer de recepção padrão tem de dezenas a centenas de KB, conforme o SO e a configuração. Em lugares cheios, as atualizações podem chegar a centenas de KB por segundo. - No gráfico: Sobe com a carga (Descartes no buffer de recepção UDP, frame time) - Onde olhar: Registrar no Monitor de Desempenho do Windows Microsoft Winsock BSP\Dropped Datagrams (datagramas UDP descartados por falta de espaço no buffer de recepção do socket) e UDPv4\Datagrams Received Errors junto com o frame time, e contar no jogo as lacunas na sequência dos pacotes recebidos - Confirma se: Em lugares cheios ou logo após frames longos, Dropped Datagrams aumenta e, no mesmo momento, surgem lacunas na sequência do jogo. No mesmo horário, não há perda do lado da conexão - Descarta se: Dropped Datagrams estável, mas com números faltando na sequência: perda no caminho - Como verificar: Verificação no ambiente do jogador - Fontes: - [socket(7) — Linux manual page](https://man7.org/linux/man-pages/man7/socket.7.html) · Linux man-pages · SO_RCVBUF é o tamanho máximo do buffer de recepção do socket; o padrão vem de rmem_default e o máximo de rmem_max (o Android também usa kernel Linux) - [SOL_SOCKET Socket Options (Winsock2.h)](https://learn.microsoft.com/en-us/windows/win32/winsock/sol-socket-socket-options) · Microsoft · SO_RCVBUF no Windows: espaço de buffer reservado para recepção em cada socket - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · O campo de janela do TCP é o número de bytes que o receptor ainda pode receber; se for 0, o emissor só envia zero window probes e espera - [Low Latency Workloads Management and Operations](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/hh997022(v=ws.11)) · Microsoft · Dropped Datagrams e Dropped Datagrams/sec do conjunto de contadores Microsoft Winsock BSP: datagramas UDP descartados porque chegaram mais rápido do que o app processa ou porque faltou espaço no buffer do socket de recepção - [Network-Related Performance Counters](https://learn.microsoft.com/en-us/windows-server/networking/technologies/network-subsystem/net-sub-performance-counters) · Microsoft · UDPv4 e UDPv6: Datagrams Received Errors; Microsoft Winsock BSP: contador Dropped Datagrams #### co-swap · Pouca memória e swap no cliente · Paging / swap on client Com dezenas de abas do navegador abertas junto com o jogo, o SO passa parte da memória do jogo para o disco. - Por quê → Efeito → Na tela: A RAM total fica insuficiente → O SO move para o disco a memória do jogo que não está em uso no momento → Quando o jogo volta a usar essa parte, a tela trava por dezenas a centenas de ms, conforme o disco - Sintomas: Travamento, Engasgos / Fatores: Paralisação - Quem: Só eu / Quando: Em movimento ou ao trocar de mapa, Aleatoriamente, de vez em quando - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Reduzir o uso de memória, mostrar um aviso quando restar pouca memória. - O que fazer (Externo): Orientar os jogadores sobre os requisitos mínimos e a fechar outros programas (abas do navegador etc.) durante o jogo. - No gráfico: Picos aleatórios (Hard page faults, uso de memória) - Onde olhar: Registrar Memory\Pages Input/sec do Monitor de Desempenho (páginas lidas do disco para resolver hard page faults) e o uso de memória e a memória confirmada na guia Desempenho do Gerenciador de Tarefas, junto com o frame time - Confirma se: No instante do travamento, Pages Input/sec dispara e a memória está quase cheia. Ao fechar o navegador e outros programas, o problema some - Descarta se: Memória com folga e Pages Input/sec quieto: “Carregamento síncrono e compilação de shaders na thread principal” ou “Streaming de assets atrasado por disco lento” - Como verificar: Verificação no ambiente do jogador - Fontes: - [Introduction to the page file](https://learn.microsoft.com/en-us/troubleshoot/windows-client/performance/introduction-to-the-page-file) · Microsoft · O arquivo de paginação é um arquivo no disco usado para tirar da RAM páginas de memória modificadas e pouco usadas - [Working Set](https://learn.microsoft.com/en-us/windows/win32/memory/working-set) · Microsoft · Acessar uma página que não está na RAM gera um page fault; um hard fault só se resolve lendo do disco, por exemplo do arquivo de paginação - [Chapter 12 - Detecting Memory Bottlenecks](https://learn.microsoft.com/en-us/previous-versions/cc749872(v=technet.10)) · Microsoft · Memory\Pages Input/sec: páginas lidas do disco para resolver page faults (hard page faults) #### co-vram · Falta de memória de vídeo (VRAM) · VRAM over-commit Quando as opções gráficas pedem mais memória do que a placa de vídeo tem, o SO tira texturas para a memória do PC e depois as traz de volta, e a imagem engasga. - Por quê → Efeito → Na tela: Opção de textura alta e, em lugares cheios, todo tipo de equipamento e efeito enchem a memória da placa de vídeo → O SO move para a memória do PC as texturas que não estão em uso no momento e, quando precisa delas, traz de volta pelo barramento PCIe, que é lento → Um engasgo a cada cena ou personagem novo que aparece, e texturas borradas por um tempo - Sintomas: Engasgos, Travamento / Fatores: Paralisação - Quem: Só eu / Quando: Quando junta muita gente, Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de desenvolvimento): Ajustar os valores padrão das opções ao tamanho da memória da placa de vídeo, reduzir automaticamente a qualidade das texturas quando o orçamento de memória estourar, simplificar as texturas dos personagens em lugares cheios. - O que fazer (Externo): Orientar os jogadores a baixar a opção de textura e a baixar ainda mais as opções quando abrirem dois clientes. - Números de referência: A memória da placa de vídeo lê centenas de GB por segundo, mas o barramento PCIe que a liga à memória do PC transfere cerca de 16–64 GB por segundo, conforme a geração; é mais de dez vezes mais lento. - No gráfico: Achata ao bater no limite (Memória dedicada da GPU, memória compartilhada da GPU) - Onde olhar: Ver os gráficos de memória dedicada e de memória compartilhada da GPU no item GPU da guia Desempenho do Gerenciador de Tarefas (na guia Detalhes, também dá para adicionar colunas por processo) junto com o frame time do PresentMon - Confirma se: Enquanto a memória dedicada da GPU fica achatada no limite e a compartilhada cresce, os engasgos ficam frequentes; ao baixar a opção de textura, eles somem - Descarta se: Memória dedicada com folga: “Streaming de assets atrasado por disco lento” ou “Carregamento síncrono e compilação de shaders na thread principal” - Como verificar: Verificação no ambiente do jogador - Saiba mais: No Gerenciador de Tarefas do Windows, no item GPU, quando a “memória dedicada da GPU” fica cheia e a “memória compartilhada da GPU” começa a crescer, é esse o caso. Com dois clientes abertos no mesmo PC, ela enche mais rápido (verbete “Falha de streaming por falta de memória ou VRAM”). - Fontes: - [Residency](https://learn.microsoft.com/en-us/windows/win32/direct3d12/residency) · Microsoft · Há um orçamento de memória gráfica que o processo pode usar; quando ele estoura, o kernel move parte do heap da GPU dedicada para a memória do PC (é o último recurso, por isso se recomenda gerenciar o orçamento) - [GPUs in the task manager](https://devblogs.microsoft.com/directx/gpus-in-the-task-manager/) · Microsoft · No Gerenciador de Tarefas, a memória dedicada da GPU é a VRAM da placa de vídeo, e a memória compartilhada da GPU é a memória do PC usada em conjunto pela GPU e pela CPU - [CUDA C++ Best Practices Guide](https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html) · NVIDIA · A largura de banda da memória gráfica (V100: 898 GB/s) é muito maior que a do PCIe x16 de 3ª geração (16 GB/s), por isso se recomenda reduzir as transferências de e para a memória do PC - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Grava o tempo de cada frame com o FrameTime (tempo de CPU entre frames) #### co-wifi-scan · Varredura de Wi-Fi em segundo plano · Periodic Wi-Fi background scan Enquanto o SO troca de canal periodicamente para procurar redes Wi-Fi próximas, a comunicação para por um instante. - Por quê → Efeito → Na tela: O SO ou o driver procura redes Wi-Fi próximas em intervalos regulares → Durante a busca, o envio e a recepção param por um instante → Picos de ping em intervalos exatamente regulares (ex.: a cada 60 s) - Sintomas: Engasgos, Teleporte / Fatores: Jitter - Quem: Só eu / Quando: Em intervalos regulares - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Pedir um modo que reduza a busca de redes sem fio durante o jogo (no Android, o modo Wi-Fi de baixa latência WIFI_MODE_FULL_LOW_LATENCY; no Windows, o modo de streaming de mídia do WlanSetInterface. Dependendo do aparelho ou do driver, pode não ter efeito). - O que fazer (Externo): Orientar os jogadores a usar cabo, ajustar as configurações de serviços de localização e de busca automática de Wi-Fi e atualizar o driver da rede sem fio. - Números de referência: Em geral, de dezenas a centenas de ms por vez. Se o padrão for regular demais, suspeite primeiro desta causa. - No gráfico: Picos em intervalos regulares (RTT até o roteador) - Onde olhar: Durante o jogo, rodar ping /t para o endereço do roteador (o gateway padrão do ipconfig) por alguns minutos e medir o intervalo entre os picos. Repetir a medição no cabo - Confirma se: O ping até o roteador dá picos de dezenas a centenas de ms em intervalos exatamente regulares (ex.: 60 s), que somem no cabo - Descarta se: Picos em intervalos irregulares: “Interferência e sinal fraco no Wi-Fi”. Até o roteador tudo normal, com picos só depois dele: aponta para a conexão ou a operadora - Como verificar: Verificação no ambiente do jogador - Fontes: - [WDI low latency connection quality](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/wdi-low-latency-connection-quality) · Microsoft · A busca e o roaming tiram o chip sem fio do canal conectado, por isso o modo de baixa latência limita o tempo fora do canal e as buscas - [WlanSetInterface function (wlanapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/wlanapi/nf-wlanapi-wlansetinterface) · Microsoft · API para ligar e desligar, no Windows, a busca em segundo plano (wlan_intf_opcode_background_scan_enabled) e o modo de streaming de mídia - [Wi-Fi low-latency mode](https://source.android.com/docs/core/connect/wifi-low-latency) · Android (Google) · No modo de baixa latência, a economia de energia do Wi-Fi é desligada; a otimização das configurações de busca e roaming depende da implementação do fabricante do aparelho - [ping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ping) · Microsoft · /t: envia solicitações de eco continuamente até ser interrompido - [ipconfig](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ipconfig) · Microsoft · Sem parâmetros, mostra os endereços IPv4 e IPv6 e o gateway padrão de cada adaptador #### co-driver · Economia de energia e problemas de driver da placa de rede · NIC power saving, driver bugs Se a placa de rede ou o chip Wi-Fi entra em modo de economia de energia entre um pacote e outro, leva um tempo para voltar à ativa. - Por quê → Efeito → Na tela: Economia de energia do dispositivo de rede ligada, ou driver desatualizado → Atraso para despertar (wake-up) e, de vez em quando, reinício do dispositivo → Atrasos irregulares e, raramente, paradas de alguns segundos - Sintomas: Engasgos, Travamento / Fatores: Jitter, Perda de pacotes - Quem: Só eu / Quando: Depois de ficar parado, Aleatoriamente, de vez em quando - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): No cliente Android, pedir o modo Wi-Fi de baixa latência (WIFI_MODE_FULL_LOW_LATENCY) durante o jogo para desligar a economia de energia do Wi-Fi. - O que fazer (Externo): Orientar os jogadores a atualizar o driver de rede e a desativar a economia de energia do dispositivo de rede no Gerenciador de Dispositivos; se a tela inteira engasgar e o som chiar, orientá-los a usar o LatencyMon para achar o driver culpado. - No gráfico: Picos aleatórios (Tempo de DPC e ISR, RTT até o roteador) - Onde olhar: Gravar com o Windows Performance Recorder (WPR), procurar no gráfico DPC/ISR do Windows Performance Analyzer (WPA) os drivers que rodam por muito tempo (coluna Module) e verificar, no Gerenciador de Dispositivos, a configuração de gerenciamento de energia do adaptador de rede - Confirma se: No horário do engasgo, DPCs e ISRs do driver de rede se estendem por alguns ms, ou os atrasos irregulares somem ao desligar a economia de energia - Descarta se: DPCs curtos e nada muda ao desligar a economia de energia: “Interferência e sinal fraco no Wi-Fi” ou “Varredura de Wi-Fi em segundo plano” - Como verificar: Verificação no ambiente do jogador - Saiba mais: Quando um driver ocupa a CPU por muito tempo tratando interrupções (no Windows, isso se chama latência de DPC), a thread do jogo também fica sem núcleo nesse tempo. Nesse caso, a tela inteira engasga e o som chia mesmo com uso de CPU baixo. Ferramentas como o LatencyMon mostram qual é o driver, e drivers de Wi-Fi e de rede cabeada são culpados comuns. - Fontes: - [Introduction to NDIS Selective Suspend](https://learn.microsoft.com/en-us/windows-hardware/drivers/network/ndis-selective-suspend) · Microsoft · O Windows pode colocar um adaptador de rede ocioso em estado de baixo consumo (suspensão seletiva) - [Guidelines for Writing DPC Routines](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/guidelines-for-writing-dpc-routines) · Microsoft · Enquanto um DPC roda, todas as threads daquele núcleo param, por isso a recomendação é não passar de 100 µs por vez - [Wi-Fi low-latency mode](https://source.android.com/docs/core/connect/wifi-low-latency) · Android (Google) · No modo Wi-Fi de baixa latência do Android, o framework desliga explicitamente a economia de energia do Wi-Fi - [CPU Analysis](https://learn.microsoft.com/en-us/windows-hardware/test/wpt/cpu-analysis) · Microsoft · Gráfico DPC/ISR do WPA: tempo de cada trecho em que DPCs e ISRs rodaram sem interrupção e o módulo (Module) que contém a função #### co-other-apps · Outros apps do mesmo dispositivo consumindo largura de banda · Other apps saturating the link Quando sincronização com a nuvem, downloads grandes ou patches de jogos rodam no mesmo PC, os pacotes do jogo esperam na fila. - Por quê → Efeito → Na tela: Outro app usa o upload ou o download no máximo → Os pacotes do jogo se acumulam na fila do PC e do roteador → Ping disparando, input lag, avanço rápido - Sintomas: Input lag, Avanço rápido / Fatores: Latência, Jitter - Quem: Só eu, Mesma casa / Quando: Aleatoriamente, de vez em quando - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Fazer nosso launcher e patcher pausarem ou limitarem a velocidade dos downloads em segundo plano durante o jogo. - O que fazer (Externo): Orientar os jogadores a limitar a velocidade de download e a desligar as atualizações automáticas durante o jogo. - No gráfico: Sobe com a carga (RTT, tráfego enviado e recebido pelo PC) - Onde olhar: Registrar juntos Network Interface\Bytes Sent/sec e Bytes Received/sec do Monitor de Desempenho e o ping. É o mesmo método do teste de bufferbloat, em que se inicia de propósito uma transferência grande com o ping rodando - Confirma se: Enquanto o download ou o upload chega perto da velocidade da conexão, o ping sobe de dezenas a centenas de ms e volta ao normal assim que a transferência para - Descarta se: Tráfego do PC baixo, mas ping subindo: “Bufferbloat (fila do roteador)” causado por outro dispositivo da mesma casa, ou trecho da operadora - Como verificar: Verificação no ambiente do jogador - Fontes: - [Introduction](https://www.bufferbloat.net/projects/bloat/wiki/Introduction/) · Bufferbloat.net · Quando equipamentos de rede como o roteador acumulam dados demais, a latência dispara (bufferbloat) - [Delivery Optimization reference](https://learn.microsoft.com/en-us/windows/deployment/do/waas-delivery-optimization-reference) · Microsoft · O download do Windows Update (Otimização de Entrega) se ajusta por padrão, de forma dinâmica, à largura de banda disponível, e dá para definir limites de banda para downloads em segundo plano e em primeiro plano - [Network-Related Performance Counters](https://learn.microsoft.com/en-us/windows-server/networking/technologies/network-subsystem/net-sub-performance-counters) · Microsoft · Network Interface: contadores Bytes Received/sec e Bytes Sent/sec - [Tests for Bufferbloat](https://www.bufferbloat.net/projects/bloat/wiki/Tests_for_Bufferbloat/) · Bufferbloat.net · Se o ping sobe ao lotar a conexão com um teste de velocidade enquanto o ping está rodando, é bufferbloat #### co-unfocused · Limitação de processamento com a janela minimizada ou inativa · Minimized / unfocused window throttling Quando você olha outra janela ou minimiza o jogo, o jogo e o Windows passam a rodá-lo mais devagar para economizar energia. Ao voltar, os pacotes acumulados chegam de uma vez, ou a conexão já caiu. - Por quê → Efeito → Na tela: O jogador troca de janela com Alt+Tab ou minimiza o jogo → Enquanto não está visível, o jogo reduz muito o FPS ou para, e o Windows também baixa a prioridade dos programas que não estão visíveis → Avanço rápido ao voltar e, se o jogo ficou minimizado por muito tempo, desconexão - Sintomas: Avanço rápido, Engasgos, Desconexão / Fatores: Paralisação - Quem: Só eu / Quando: Ao fazer ações específicas, Depois de ficar parado - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Manter a recepção de pacotes e o heartbeat em uma thread separada mesmo com a janela invisível, verificar a configuração “rodar em segundo plano” da engine, sincronizar com o estado mais recente de uma vez ao voltar. - Números de referência: Se o FPS cai para 5–10 com a janela invisível, cada frame dura 100–200 ms. Jogos que processam pacotes a cada frame leem os pacotes com esse mesmo atraso. - No gráfico: Lacuna e depois tudo junto (Intervalo entre frames (antes e depois de trocar de janela), pacotes processados) - Onde olhar: Com o PresentMon ligado, testar Alt+Tab e minimizar o jogo, observando o intervalo entre frames com a janela invisível. Registrar no log do jogo os horários de mudança de foco da janela e cruzar com o motivo das desconexões - Confirma se: Com a janela invisível, o intervalo entre frames passa de 100 ms ou o registro para; ao voltar, os pacotes acumulados são processados de uma vez, em avanço rápido. Com a janela minimizada por muito tempo, a conexão cai por timeout de heartbeat - Descarta se: Igual mesmo com a janela aberta: “Processos em segundo plano ocupando a CPU” ou rede - Como verificar: Verificação no ambiente do jogador - Saiba mais: O Windows 11 não garante o timer de 1 ms a programas com janelas minimizadas ou totalmente encobertas que não estejam emitindo som. Em notebooks na bateria, esses programas passam a rodar na velocidade de menor consumo e, em CPUs com tipos diferentes de núcleo, podem ir para os núcleos de eficiência, mais lentos. Se, de dois clientes no mesmo PC, só o que está em segundo plano apresenta problemas, veja também o verbete “Limitação de processamento da janela em segundo plano”. - Fontes: - [Quality of Service](https://learn.microsoft.com/en-us/windows/win32/procthread/quality-of-service) · Microsoft · Programas com janela invisível e sem som ficam em Low QoS e, na bateria, são escalonados na velocidade de CPU mais eficiente e nos núcleos de eficiência - [timeBeginPeriod function (timeapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod) · Microsoft · O Windows 11 não garante resolução de timer acima do padrão para processos com janelas encobertas ou minimizadas - [Application.runInBackground](https://docs.unity3d.com/ScriptReference/Application-runInBackground.html) · Unity · O padrão do Unity é false, então o game loop para quando a janela vai para segundo plano - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · MsBetweenPresents: tempo entre esta chamada de Present() e a anterior (ms) #### co-overlay · Interferência de programas de overlay · Overlays and screen hooks Mensageiros, launchers, gravadores e programas que mostram FPS entram no processo de renderização do jogo (hooking) para desenhar a própria UI por cima da tela. Cada frame ganha mais trabalho e, de vez em quando, o overlay entra em conflito com o jogo, causando engasgos ou o encerramento forçado do jogo. - Por quê → Efeito → Na tela: Overlay de mensageiro, launcher de jogos, ferramenta da placa de vídeo ou gravador ligado → A cada frame enviado para a tela, o overlay entra no meio e desenha a própria UI por cima → Frames um pouco atrasados e, quando aparece uma notificação, um engasgo, erro gráfico ou encerramento forçado (para o jogador, parece uma desconexão) - Sintomas: Engasgos, Travamento, Desconexão / Fatores: Paralisação - Quem: Só eu / Quando: Sempre, Aleatoriamente, de vez em quando - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Coletar, junto com os relatórios de crash e os logs de engasgos, a lista de overlays em execução. - O que fazer (Externo): Quando chegar um report, orientar o jogador a desligar todos os overlays e testar de novo. - No gráfico: Alto só em alguns (Frame time e número de crashes (jogadores com overlay ligado)) - Onde olhar: Desligar todos os overlays e comparar o frame time do PresentMon na mesma cena; se houver crash, ver o nome do módulo com falha (Faulting module name) no evento com ID 1000 do Visualizador de Eventos - Confirma se: Os engasgos e erros gráficos somem ao desligar os overlays, ou o módulo com falha do crash é a DLL de um programa de overlay - Descarta se: Igual mesmo com todos os overlays desligados: driver de vídeo ou “Crash do cliente” - Como verificar: Verificação no ambiente do jogador - Saiba mais: Quando só certos jogadores têm engasgos ou quedas do jogo e a configuração do PC não explica o problema, suspeite primeiro de um conflito entre o overlay e o módulo de segurança do jogo. - Fontes: - [Steam Overlay (Steamworks Documentation)](https://partner.steamgames.com/doc/features/overlay) · Valve · O overlay da Steam faz hooking automático nos jogos iniciados pela Steam e, por esse método, pode expor erros de memória no uso da API de renderização pelo jogo e causar crashes - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · Grava o tempo de cada frame com o FrameTime (tempo de CPU entre frames) - [The application or service crashing behavior troubleshooting guidance](https://learn.microsoft.com/en-us/troubleshoot/windows-server/performance/troubleshoot-application-service-crashing-behavior) · Microsoft · No log de Aplicativo, o evento com ID 1000 traz o nome do módulo com falha (Faulting module name); às vezes um módulo do Windows aparece como módulo com falha por causa de dano causado por outro módulo #### co-display-input · Latência da tela, do dispositivo de entrada e da geração de frames · Display, input device and frame generation latency Se o ping está normal, mas o controle parece pesado, o processamento de imagem da TV, o controle sem fio ou a geração de frames podem estar somando latência entre o comando e a tela. - Por quê → Efeito → Na tela: Modo de jogo da TV desligado, controle Bluetooth ou sem fio, ou geração de frames ligada (geração de frames do DLSS ou do FSR) → A TV atrasa a saída dos frames enquanto processa a imagem, o input sem fio chega atrasado pelo ciclo de envio e pela interferência, e a geração de frames espera o próximo frame para criar o frame intermediário → Ping e FPS bons, mas o que você aperta demora a aparecer na tela: input lag - Sintomas: Input lag / Fatores: Latência - Quem: Só eu / Quando: Sempre - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Deixar a geração de frames como opção e avisar que, ligada, ela pode aumentar o input lag, integrar a geração de frames com os recursos de baixa latência do fabricante da GPU (NVIDIA Reflex, AMD Anti-Lag 2), mostrar no jogo a latência do input até a tela do lado do PC, pedir à TV o modo de baixa latência (ALLM) com Window.setPreferMinimalPostProcessing(true) nas builds para Android TV e set-top box. - O que fazer (Externo): Orientar os jogadores a ativar o modo de jogo (ALLM) da TV ou do monitor, a usar controle com fio e desligar a geração de frames em conteúdo competitivo, e a deixar os dispositivos Bluetooth por perto e usar Wi-Fi de 5 GHz. - Números de referência: Uma tela de 60 Hz leva 16,7 ms só para enviar um frame; a 120 Hz, 8,3 ms. Controles antigos do Xbox liam e enviavam o input a cada 8 ms. A latência que o processamento de imagem da TV acrescenta varia de aparelho para aparelho, por isso é difícil dar um número único; o modo de jogo é a configuração que reduz esse processamento. A AMD recomenda usar a geração de frames quando o jogo já roda a pelo menos 60 FPS sem ela. - No gráfico: Sempre alto desde o início (Latência do input até a tela) - Onde olhar: Comparar no PresentMon MsAllInputToPhotonLatency (do input de teclado e mouse até o envio para a tela) com a geração de frames ligada e desligada e ver em FrameType (registrado só quando o driver ou o SDK informam) se há frames intermediários gerados no meio. Esse valor não inclui o trecho sem fio do controle nem o processamento dentro da TV; para essa parte, comparar alternando o modo de jogo da TV e o controle com fio - Confirma se: Ping normal, e a latência do input até a tela diminui ao desligar a geração de frames, ou a latência sentida some ao trocar para o modo de jogo da TV ou para um controle com fio - Descarta se: Nada muda ao alterar todas essas configurações, e o ping está alto ou com picos: aponta para a rede. Latência do lado do PC alta por causa do V-Sync ou da fila de frames: “V-Sync e fila de renderização” - Como verificar: Verificação no ambiente do jogador - Saiba mais: A latência de rede aparece no ping; esta latência, não. Por isso, é o primeiro lugar a verificar em reports de “ping baixo, mas com lag”. A geração de frames quase dobra o número de FPS na tela, mas, para criar o frame intermediário, precisa esperar o próximo frame real, então o tempo até o comando aparecer na tela aumenta (a AMD afirma que, por design, a latência aumenta). Dispositivos Bluetooth usam a mesma faixa de 2,4 GHz do Wi-Fi e, com interferência, o input pode falhar ou oscilar. Para V-Sync e fila de renderização, que aumentam a latência dentro do PC, veja o verbete “V-Sync e fila de renderização”. - Fontes: - [Auto Low Latency Mode (ALLM)](https://www.hdmi.org/spec21sub/autolowlatencymode) · HDMI Licensing Administrator · O ALLM faz o aparelho mudar a tela automaticamente para o modo de baixa latência (em geral, o modo de jogo); nesse modo, parte do processamento de imagem da TV é desligada para reduzir a latência - [Xbox Series X: What’s the Deal with Latency?](https://news.xbox.com/en-us/2020/03/16/xbox-series-x-latency/) · Microsoft · O input lag é a soma do caminho controle → console → HDMI → TV; controles antigos liam e enviavam o input a cada 8 ms; tempo para enviar um frame por HDMI: 16,6 ms a 60 Hz e 8,3 ms a 120 Hz; o ALLM muda a TV automaticamente para o modo de jogo - [AMD FSR 3 game integrations out now + more details for developers](https://gpuopen.com/news/fsr3-in-games-technical-details/) · AMD · Por design, a interpolação de frames aumenta a latência; recomenda-se usar com pelo menos 60 FPS antes da interpolação; com entrada de 60 FPS, saída de até 120 FPS - [AMD FSR Frame Generation](https://gpuopen.com/amd-fsr-framegeneration/) · AMD · Para geração de frames, recomenda-se pelo menos 60 FPS antes da interpolação (abaixo de 30 FPS, deve ser evitada); o AMD Radeon Anti-Lag 2 alinha o trabalho de CPU e GPU para reduzir a latência do sistema - [NVIDIA DLSS](https://developer.nvidia.com/rtx/dlss) · NVIDIA · A geração de frames do DLSS foi projetada para manter a responsividade junto com o NVIDIA Reflex (recurso de baixa latência) - [Resolve Wi-Fi and Bluetooth issues caused by wireless interference](https://support.apple.com/en-us/102319) · Apple · A interferência sem fio causa quedas e perda de desempenho em dispositivos Wi-Fi e Bluetooth, e Bluetooth e Wi-Fi usam a mesma faixa de 2,4 GHz - [PresentMon Capture Application (README-CaptureApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-CaptureApplication.md) · Intel · MsAllInputToPhotonLatency (latência do input até a tela), DisplayLatency (do envio do frame até a saída para o monitor), FrameType (distingue frames desenhados pelo app de frames interpolados pelo driver ou SDK) - [PresentMon Console Application (README-ConsoleApplication.md)](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README-ConsoleApplication.md) · Intel · MsAllInputToPhotonLatency considera o input de teclado e mouse; FrameType só é registrado se o app ou o driver emitir eventos Intel-PresentMon (--track_frame_type) - [Window.setPreferMinimalPostProcessing](https://developer.android.com/reference/android/view/Window#setPreferMinimalPostProcessing(boolean)) · Android (Google) · Janelas em que a latência importa, como as de jogos, pedem à tela o mínimo de processamento de imagem; em conexões HDMI, são enviados os sinais ALLM e Game Content Type para colocar a TV em modo de baixa latência ### L3 Rede doméstica (10 causas) #### hn-wifi · Interferência e sinal fraco no Wi-Fi · Wi-Fi interference, weak signal Com sinal fraco ou interferência, o trecho sem fio precisa reenviar várias vezes, e a chegada dos pacotes fica irregular. - Por quê → Efeito → Na tela: Paredes, distância, micro-ondas, Bluetooth e roteadores vizinhos degradam o sinal → Falhas de transmissão no trecho sem fio → várias retransmissões → A chegada dos pacotes fica irregular (jitter), e os personagens se movem engasgando; nos casos graves, a perda causa teleporte - Sintomas: Engasgos, Teleporte, Rubber banding / Fatores: Jitter, Perda de pacotes - Quem: Só eu, Mesma casa / Quando: Aleatoriamente, de vez em quando, Sempre - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Ajustar automaticamente o tamanho do buffer de interpolação conforme o estado da conexão, mostrar na tela o estado da rede quando jitter e perda estiverem altos. - O que fazer (Externo): Orientar os jogadores a usar cabo, usar 5 GHz ou 6 GHz e mudar o roteador de lugar. - Números de referência: Cada retransmissão acrescenta cerca de 1–4 ms. Com sinal fraco, o Wi-Fi reenvia várias vezes a uma velocidade menor e ainda espera o canal ficar livre, e os picos podem chegar a 50–200 ms. A armadilha é que o ping médio parece normal. - No gráfico: Picos aleatórios (RTT até o roteador) - Onde olhar: Rodar ping /t para o endereço do roteador (o gateway padrão do ipconfig) por alguns minutos e ver a intensidade do sinal e o canal do seu roteador com netsh wlan show networks mode=bssid. Comparar no mesmo lugar trocando para cabo - Confirma se: Os picos irregulares de dezenas a centenas de ms, com perda de vez em quando, já aparecem no ping até o roteador, e a intensidade do sinal está baixa. No cabo ou perto do roteador, o problema some - Descarta se: Até o roteador estável, com picos só depois dele: aponta para a conexão ou a operadora. Picos só em intervalos fixos: “Varredura de Wi-Fi em segundo plano” - Como verificar: Verificação no ambiente do jogador - Saiba mais: Em um Wi-Fi mesh em que os roteadores (nós) se ligam entre si sem fio (backhaul sem fio), o nó que repassa os dados não consegue transmitir enquanto recebe e divide as oportunidades de transmissão com os trechos vizinhos que usam o mesmo canal; com a rede cheia, a vazão pode cair e a latência pode aumentar. Produtos com uma faixa sem fio dedicada ao backhaul sofrem menos, e ligar os nós por cabo (Ethernet) tira esse trecho do sem fio. Adaptadores powerline (PLC) também usam, como o Wi-Fi, um método que verifica se o meio está livre antes de transmitir (CSMA/CA), e a qualidade muda o tempo todo com o ruído dos eletrodomésticos e com eles sendo ligados e desligados, o que pode gerar retransmissões e jitter. - Casos reais: ffxiv-2021 - Fontes: - [Resolve Wi-Fi and Bluetooth issues caused by wireless interference](https://support.apple.com/en-us/102319) · Apple · Fontes de interferência como micro-ondas e telefones sem fio; Wi-Fi e Bluetooth usam a mesma faixa de 2,4 GHz; recomenda-se passar para 5 GHz e escolher um canal com menos interferência - [RFC 8325: Mapping Diffserv to IEEE 802.11](https://www.rfc-editor.org/rfc/rfc8325) · IETF · CSMA/CA do 802.11: só transmite com o canal livre; se estiver ocupado, adia até liberar e ainda espera um backoff aleatório - [Ending the Anomaly: Achieving Low Latency and Airtime Fairness in WiFi (USENIX ATC 2017)](https://www.usenix.org/system/files/conference/atc17/atc17-hoiland-jorgensen.pdf) · USENIX · Sob carga, a fila padrão do Wi-Fi gera centenas de ms de latência; dispositivos conectados a baixa velocidade (sinal fraco) passam de 200 ms de mediana mesmo com FQ-CoDel - [ping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ping) · Microsoft · /t: envia solicitações de eco continuamente até ser interrompido - [ipconfig](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ipconfig) · Microsoft · Sem parâmetros, mostra os endereços IPv4 e IPv6 e o gateway padrão de cada adaptador - [Wireless network connectivity issues troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/wireless-network-connectivity-issues-troubleshooting) · Microsoft · netsh wlan show networks mode=bssid: mostra, para cada Wi-Fi visível, o BSSID, a intensidade do sinal, o canal e o padrão de rádio - [Capacity of Ad Hoc Wireless Networks (MobiCom 2001)](https://pdos.csail.mit.edu/papers/grid:mobicom01/paper.pdf) · ACM · Com vários saltos de repetição sem fio 802.11, o nó não consegue transmitir enquanto recebe e os trechos vizinhos interferem entre si; a vazão de uma rota em cadeia cai, em teoria, para até 1/3 (cerca de 1/7 em simulação) - [Electri-Fi Your Data: Measuring and Combining Power-Line Communications with WiFi (IMC 2015)](https://conferences.sigcomm.org/imc/2015/papers/p325.pdf) · ACM · Equipamentos comerciais de comunicação pela rede elétrica (IEEE 1901, HomePlug AV) transmitem com CSMA/CA, parecido com o do Wi-Fi, e o jitter pode aumentar por desequilíbrios de curto prazo no acesso ao meio; a qualidade do canal muda com o ruído dos eletrodomésticos e com eles sendo ligados e desligados (em escalas de minutos a horas) #### hn-channel · Canal de Wi-Fi congestionado · Crowded Wi-Fi channel Em lugares com dezenas de roteadores, como prédios de apartamentos, todos dividem o mesmo canal e esperam a vez de transmitir. - Por quê → Efeito → Na tela: Dezenas de roteadores usam o mesmo canal de 2,4 GHz → Para transmitir, é preciso esperar os outros dispositivos terminarem e o canal ficar livre → À noite, quando as pessoas chegam em casa, o jitter (variação no intervalo de chegada dos pacotes) aumenta e a imagem engasga - Sintomas: Engasgos, Input lag / Fatores: Jitter, Latência - Quem: Mesma casa / Quando: Horário de pico à noite - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Aumentar automaticamente o buffer de interpolação quando o jitter subir. - O que fazer (Externo): Orientar os jogadores a usar 5 GHz ou 6 GHz, um canal menos congestionado ou cabo. - No gráfico: Alto só em certos horários (RTT e jitter até o roteador) - Onde olhar: Ver com netsh wlan show networks mode=bssid os canais e a intensidade de sinal das redes Wi-Fi próximas e comparar o ping até o roteador à noite e durante o dia - Confirma se: Muitos roteadores vizinhos aparecem no mesmo canal de 2,4 GHz, e o jitter até o roteador só aumenta à noite. Passando para 5 GHz, 6 GHz ou um canal menos congestionado, o jitter diminui - Descarta se: Picos em qualquer horário: “Interferência e sinal fraco no Wi-Fi”. Até o roteador tudo bem, mas à noite o trecho depois dele piora: “Congestionamento no peering em horário de pico” - Como verificar: Verificação no ambiente do jogador - Fontes: - [Recommended settings for Wi-Fi routers and access points](https://support.apple.com/en-us/102766) · Apple · Outros roteadores e dispositivos no mesmo canal são fontes de interferência; em 2,4 GHz, recomenda-se largura de 20 MHz; em 5 GHz e 6 GHz, a interferência preocupa menos - [RFC 8325: Mapping Diffserv to IEEE 802.11](https://www.rfc-editor.org/rfc/rfc8325) · IETF · Com o canal ocupado, o 802.11 adia a transmissão até ele ficar livre e transmite depois de um backoff aleatório (CSMA/CA) - [Wireless network connectivity issues troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/wireless-network-connectivity-issues-troubleshooting) · Microsoft · netsh wlan show networks mode=bssid: mostra, para cada Wi-Fi visível, o BSSID, a intensidade do sinal, o canal e o padrão de rádio - [ping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ping) · Microsoft · /t: envia solicitações de eco continuamente até ser interrompido #### hn-bufferbloat · Bufferbloat (fila do roteador) · Bufferbloat Quando alguém da família sobe um vídeo ou baixa um arquivo grande, a fila do roteador acumula centenas de ms de pacotes, e os pacotes do jogo esperam atrás deles. - Por quê → Efeito → Na tela: Upload de vídeo ou backup na nuvem de alguém da família, sua transmissão ao vivo ou um download grande lotam a conexão → O roteador ou o modem guarda o excesso de pacotes em uma fila grande → Os pacotes do jogo também esperam no fim da fila, e o ping dispara para centenas de ms - Sintomas: Input lag, Avanço rápido, Teleporte / Fatores: Latência, Jitter - Quem: Mesma casa, Só eu / Quando: Aleatoriamente, de vez em quando, Horário de pico à noite - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Mostrar na tela o estado da rede quando o ping subir de repente para centenas de ms (avisando que pode haver uma transferência grande na mesma conexão). - O que fazer (Externo): Orientar os jogadores a usar roteador com SQM (fq_codel, CAKE) ou QoS, a configurar a velocidade do SQM em 90–95% da velocidade da conexão (assim a fila se forma dentro do roteador e o SQM funciona) e a limitar a velocidade de upload. - Números de referência: Em uma conexão com 10 Mbps de upload e buffer de 1 MB, a fila pode chegar a 800 ms. - No gráfico: Sobe com a carga (RTT, uso de upload e download da conexão) - Onde olhar: Lotar a conexão com um teste de velocidade com o ping rodando, ou usar um teste web que mede a latência sob carga (orientação da Bufferbloat.net). Ver junto com o uso de upload e download na página de configuração do roteador - Confirma se: Enquanto o upload ou o download lota a conexão, o ping sobe para centenas de ms e volta quando a transferência termina (suspeite se a latência sob carga passar de 50 ms). Ativando o SQM, o problema some - Descarta se: Ping com picos mesmo com a conexão ociosa: “Interferência e sinal fraco no Wi-Fi” ou “Qualidade ruim da linha” - Como verificar: Verificação no ambiente do jogador - Saiba mais: O upload é o lado que mais entope. Isso porque, em conexões a cabo e móveis, o upload costuma ser bem mais estreito que o download. Em casas com fibra de sobra, o gargalo passa a ser o trecho do Wi-Fi, e o mesmo acontece na fila sem fio do roteador. Os pacotes do jogo são pequenos e quase não usam banda, mas precisam esperar na fila do mesmo jeito. Se só o upload estiver entupido, só os seus comandos atrasam, e o movimento dos outros fica normal. No celular, o backup de fotos e as atualizações de apps do próprio aparelho enchem as filas do modem do celular e da antena, e acontece a mesma coisa. - Fontes: - [Setting up SQM for CeroWrt 3.10](https://www.bufferbloat.net/projects/cerowrt/wiki/Setting_up_SQM_for_CeroWrt_310/) · Bufferbloat.net · É preciso baixar a velocidade do SQM para 95% da velocidade medida (85% se for com base na velocidade anunciada) para trazer o gargalo do equipamento da operadora para dentro do roteador e o SQM funcionar - [SQM (Smart Queue Management)](https://openwrt.org/docs/guide-user/network/traffic-shaping/sqm) · OpenWrt · Informar 90% da velocidade medida de download e upload; como disciplina de fila, recomenda-se cake (fq_codel se a CPU for fraca) - [Ending the Anomaly: Achieving Low Latency and Airtime Fairness in WiFi (USENIX ATC 2017)](https://www.usenix.org/system/files/conference/atc17/atc17-hoiland-jorgensen.pdf) · USENIX · Quando o trecho Wi-Fi lota, surge latência de centenas de ms na fila sem fio do roteador; corrigindo a fila sem fio, a latência sob carga cai para cerca de 1/10 - [Tests for Bufferbloat](https://www.bufferbloat.net/projects/bloat/wiki/Tests_for_Bufferbloat/) · Bufferbloat.net · Se o ping sobe ao lotar a conexão com um teste de velocidade enquanto o ping está rodando, é bufferbloat; com latência sob carga acima de 50 ms (ou nota abaixo de B), recomenda-se tomar medidas #### hn-nat · Expiração do mapeamento NAT · NAT mapping timeout O roteador apaga da tabela NAT as conexões ociosas, sem tráfego por um tempo. É uma causa comum de a conexão cair no instante em que o jogador volta a se mexer depois de ficar parado. - Por quê → Efeito → Na tela: O roteador registra a conexão “dispositivo de dentro ↔ servidor de fora” na tabela NAT (tabela de tradução de endereços) → Sem pacotes por um tempo, a entrada é apagada da tabela (no UDP, em geral 30–120 s) → Os pacotes do servidor não conseguem entrar na casa, e a conexão cai - Sintomas: Desconexão / Fatores: Perda de pacotes - Quem: Só eu, Mesma casa / Quando: Depois de ficar parado - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: enviar heartbeats em intervalo de no máximo metade do menor timeout de inatividade (o mapeamento UDP só é renovado com certeza por pacotes que saem de dentro da casa, por isso quem envia é o cliente), reconectar automaticamente se cair. Servidor: responder aos heartbeats, encerrar a conexão por conta própria se ficar um tempo sem recebê-los e, mesmo que o mapeamento seja apagado e o endereço e a porta externos mudem, confirmar pelo token de sessão (o código de confirmação recebido na conexão) que é o mesmo jogador e retomar a sessão. - No gráfico: Queda de conexões em massa (Desconexões (timeout de heartbeat), tempo ocioso antes da queda) - Onde olhar: Reunir os motivos de desconexão no servidor e o tempo decorrido desde o último pacote trocado naquela conexão antes da queda (tempo ocioso) e ver a distribuição. Para testar, aumentar o intervalo entre pacotes UDP para 30 s, 60 s e 120 s e medir em qual intervalo as respostas param - Confirma se: Só caem conexões que estavam paradas, e o tempo ocioso se concentra logo acima de um valor específico (algo entre 30 e 120 s). Com heartbeats em intervalo menor que esse, o problema some - Descarta se: Cai mesmo em movimento: aponta para a conexão ou a rota. Concentrado em valores curtos só em certa operadora móvel: “IP compartilhado pela operadora (CGNAT)” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP](https://www.rfc-editor.org/rfc/rfc4787) · IETF · O timer de mapeamento UDP não pode expirar antes de 2 minutos, e o padrão recomendado é de 5 minutos ou mais; a renovação por pacotes de saída é obrigatória, e a renovação por pacotes de entrada é opcional - [An Experimental Study of Home Gateway Characteristics (IMC 2010)](https://conferences.sigcomm.org/imc/2010/papers/p260.pdf) · ACM · Medição em 34 roteadores domésticos: o mapeamento UDP durou 30–691 s, com mediana de 90 s, e mais da metade ficou abaixo de 2 minutos; no TCP, mediana de cerca de 60 minutos - [RFC 9308: Applicability of the QUIC Transport Protocol](https://www.rfc-editor.org/rfc/rfc9308) · IETF · Na internet com NAT no caminho, um keep-alive a cada 30 s, mais ou menos, é adequado; com mais frequência, há desperdício de tráfego e de energia #### hn-router · Roteador fraco ou superaquecido · Router CPU / session table exhaustion Quando um roteador barato recebe dezenas de dispositivos e milhares de conexões, o próprio roteador não dá conta de processar tudo. - Por quê → Efeito → Na tela: Dezenas de dispositivos, P2P e torrent abrem milhares de conexões → A CPU e a tabela de sessões do roteador saturam → Atraso e perda no processamento de pacotes, falha em novas conexões - Sintomas: Engasgos, Não conecta / loading infinito, Desconexão / Fatores: Perda de pacotes, Jitter - Quem: Mesma casa / Quando: Quanto mais tempo ligado, Aleatoriamente, de vez em quando - Responsável principal: Externo (Externo) - O que fazer (Externo): Orientar os jogadores a reiniciar o roteador (paliativo), trocar o roteador e fechar programas que abrem muitas conexões (P2P, torrent). - No gráfico: Achata ao bater no limite (CPU e número de conexões do roteador, RTT até o roteador) - Onde olhar: Ver na página de configuração do roteador o uso de CPU, o número de conexões (sessões) e o número de dispositivos conectados (se o roteador mostrar) e comparar o ping até o próprio roteador antes e depois de reiniciá-lo - Confirma se: Com muitas conexões, os picos ou as perdas já aparecem no ping até o roteador, e as novas conexões falham. Depois de reiniciar, fica bem por um tempo e volta a piorar - Descarta se: Até o roteador normal, piorando só depois dele: aponta para a conexão ou a operadora - Como verificar: Verificação no ambiente do jogador - Fontes: - [An Experimental Study of Home Gateway Characteristics (IMC 2010)](https://conferences.sigcomm.org/imc/2010/papers/p260.pdf) · ACM · O número de conexões TCP que um roteador doméstico aceita para uma porta de servidor vai de 16 a cerca de 1.024 (mediana de 135), e equipamentos baratos às vezes ficam em uma vazão de poucos Mbps - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · Número máximo de entradas na tabela de rastreamento de conexões do Linux (nf_conntrack_max) e tempos de retenção padrão por estado #### hn-handover · Handover entre antenas (em movimento) · Cellular handover Ao se deslocar de ônibus ou metrô, a comunicação cai enquanto o celular troca de antena. - Por quê → Efeito → Na tela: Em movimento, a antena à qual o celular está conectado muda → Normalmente, é um intervalo de dezenas de ms, mas, se o sinal estiver ruim e a troca falhar, a comunicação pode cair por centenas de ms a alguns segundos → Pausa e depois teleporte; se demorar, desconexão - Sintomas: Travamento, Teleporte, Desconexão / Fatores: Perda de pacotes - Quem: Só eu / Quando: Em movimento ou ao trocar de mapa - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: usar um timeout que tolere quedas curtas, reconectar rápido. Servidor: usar um timeout que não expulse o jogador na hora por alguns segundos de queda, retomar a mesma sessão na reconexão. - O que fazer (Externo): Explicar aos jogadores que as quedas em movimento (ônibus, metrô) acontecem por causa da troca de antena. - No gráfico: Lacuna e depois tudo junto (Pacotes recebidos, RTT) - Onde olhar: Verificar se a queda reportada aconteceu em movimento (ônibus, metrô) e ver no log do cliente os horários das lacunas na recepção e as mudanças de tipo de rede e de sinal - Confirma se: Só em movimento a recepção fica vazia por centenas de ms a alguns segundos e depois chega tudo de uma vez; parado, o problema não se reproduz - Descarta se: Igual mesmo parado: “Sinal de celular fraco e áreas de sombra” ou “Troca frequente 5G↔LTE (borda da cobertura 5G)” - Como verificar: Verificação no ambiente do jogador - Fontes: - [Report ITU-R M.2134: Requirements related to technical performance for IMT-Advanced radio interface(s)](https://www.itu.int/pub/R-REP-M.2134-2008) · ITU · Requisito de tempo sem troca de dados durante o handover: 27,5 ms na mesma frequência, 40–60 ms entre frequências diferentes - [Understanding Operational 5G: A First Measurement Study on Its Coverage, Performance and Energy Consumption (SIGCOMM 2020)](https://xyzhang.ucsd.edu/papers/DXu_SIGCOMM20_5Gmeasure.pdf) · ACM · Latência de handover medida em redes comerciais: média de 30 ms em 4G↔4G e média de 108 ms entre células 5G (NSA) #### hn-rrc · Atraso na transição de estado RRC (economia de energia do rádio móvel) · Radio state promotion (RRC) Depois de um tempo sem comunicação, o celular coloca a conexão de rádio em estado de baixo consumo e, no pacote seguinte, demora para reativá-la. - Por quê → Efeito → Na tela: Depois de um tempo sem comunicação, o celular passa a conexão de rádio para o modo de economia de energia → Para enviar o próximo pacote, é preciso reativar a conexão → Só a primeira ação depois de ficar parado demora mais - Sintomas: Input lag / Fatores: Latência - Quem: Só eu / Quando: Depois de ficar parado - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Manter o rádio ativo com envios periódicos leves (em troca de mais consumo de bateria). - Números de referência: No LTE, em geral a conexão entra em economia de energia depois de uns 10 segundos sem comunicação, e reativá-la leva de dezenas a centenas de ms (exemplo medido: cerca de 0,3–0,6 s). No 3G, mais de 1 segundo. - No gráfico: Alto só em alguns (RTT da primeira requisição após inatividade (mobile)) - Onde olhar: Separar o RTT do jogo pelo intervalo desde a comunicação anterior. No mobile, comparar o RTT do primeiro pacote enviado depois de mais de 10 segundos parado com o de pacotes enviados em sequência - Confirma se: Na rede móvel, só o primeiro pacote depois de uma pausa chega centenas de ms atrasado, e os pacotes enviados em seguida estão normais. No Wi-Fi, não há diferença - Descarta se: Atrasado mesmo enviando em sequência: aponta para o sinal, a conexão ou a rota - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [An In-depth Study of LTE: Effect of Network Protocol and Application Behavior on Performance (SIGCOMM 2013)](https://conferences.sigcomm.org/sigcomm/2013/papers/sigcomm/p363.pdf) · ACM · Na rede LTE medida, o timer de transição para economia de energia (tail) é de 10 s, e a latência para sair da economia tem mediana de 435 ms (25–75%: 319–558 ms); no 3G, cerca de 1,5–2 s - [Optimize network access](https://developer.android.com/develop/connectivity/network-ops/network-access-optimization) · Android (Google) · A latência das transições de estado do rádio e o tempo de tail variam com a tecnologia (3G, LTE, 5G) e a configuração da operadora; exemplo no 3G: de baixo consumo para potência máxima, cerca de 1,5 s; de espera para potência máxima, mais de 2 s - [Report ITU-R M.2134: Requirements related to technical performance for IMT-Advanced radio interface(s)](https://www.itu.int/pub/R-REP-M.2134-2008) · ITU · Requisito de latência do plano de controle para passar do estado de espera ao estado ativo: menos de 100 ms (sem contar o paging e o trecho cabeado) #### hn-weak-cell · Sinal de celular fraco e áreas de sombra · Weak cellular signal Em elevadores, subsolos e no interior de prédios, as retransmissões aumentam, a velocidade cai e, no fim, a conexão cai. - Por quê → Efeito → Na tela: O jogador vai para um lugar com sinal fraco → Mais retransmissões no rádio, queda de velocidade, interrupções momentâneas → Jitter e perda causam engasgos e teleporte e, no fim, desconexão - Sintomas: Engasgos, Teleporte, Desconexão / Fatores: Jitter, Perda de pacotes - Quem: Só eu / Quando: Em movimento ou ao trocar de mapa - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Refinar o fluxo de reconexão, mostrar a qualidade da rede. - O que fazer (Externo): Explicar aos jogadores que o problema acontece em lugares com sinal fraco (elevadores, subsolos, interior de prédios). - No gráfico: Alto só em alguns (RTT e perda (por jogador mobile)) - Onde olhar: Verificar o lugar onde a queda foi reportada (elevador, subsolo, interior de prédio) e o indicador de sinal do celular, e comparar repetindo a mesma ação em um lugar com sinal bom - Confirma se: RTT e perda aumentam e a conexão cai só em lugares com sinal fraco; indo para um lugar com sinal bom, o problema some - Descarta se: Igual mesmo com sinal bom: aponta para o trecho da operadora ou para o servidor - Como verificar: Verificação no ambiente do jogador - Fontes: - [An In-depth Study of LTE: Effect of Network Protocol and Application Behavior on Performance (SIGCOMM 2013)](https://conferences.sigcomm.org/sigcomm/2013/papers/sigcomm/p363.pdf) · ACM · O LTE esconde a perda no trecho de rádio com retransmissões nas camadas física e MAC; a largura de banda disponível varia muito, de segundo a segundo, conforme a intensidade do sinal e outros fatores #### hn-5g-flip · Troca frequente 5G↔LTE (borda da cobertura 5G) · 5G NSA / LTE switching Dentro de prédios com sinal 5G fraco ou na borda da cobertura 5G, o celular alterna com frequência entre 5G e LTE e, a cada troca, o ping dá um pico ou a comunicação cai por um instante. - Por quê → Efeito → Na tela: O jogador está em um lugar com sinal 5G instável (dentro de prédio, borda do 5G) → O celular alterna o tempo todo entre 5G e LTE, e a cada troca surge um intervalo curto sem comunicação → Mesmo parado, picos de ping sem padrão e, de vez em quando, travamentos e teleporte - Sintomas: Engasgos, Teleporte, Travamento / Fatores: Jitter, Perda de pacotes - Quem: Só eu / Quando: Aleatoriamente, de vez em quando, Em movimento ou ao trocar de mapa - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Aumentar automaticamente o buffer de interpolação quando o jitter subir, registrar nos logs gerados quando há lag as mudanças de tipo de rede (5G, LTE) para distinguir a causa. - O que fazer (Externo): Orientar os jogadores a mudar para o modo LTE preferencial nas configurações e comparar, recomendar o uso de Wi-Fi. - Números de referência: Cada troca leva de dezenas a centenas de ms. Na Coreia, a maior parte do 5G funciona no modo combinado com o LTE (NSA), por isso é comum só a parte 5G conectar e desconectar. - No gráfico: Picos aleatórios (RTT, mudanças de tipo de rede (5G/LTE)) - Onde olhar: Mudar a configuração do celular para LTE preferencial e comparar no mesmo lugar. Se o cliente registrar as mudanças do indicador de rede do TelephonyDisplayInfo do Android (OVERRIDE_NETWORK_TYPE_NR_NSA etc.) junto com o RTT, a confirmação fica mais segura - Confirma se: Os horários dos picos de RTT coincidem com as trocas do indicador 5G↔LTE, e os picos somem no modo LTE preferencial - Descarta se: Picos mesmo sem mudança no indicador de rede: “Sinal de celular fraco e áreas de sombra” ou conexão - Como verificar: Verificação no ambiente do jogador - Fontes: - [Understanding Operational 5G: A First Measurement Study on Its Coverage, Performance and Energy Consumption (SIGCOMM 2020)](https://xyzhang.ucsd.edu/papers/DXu_SIGCOMM20_5Gmeasure.pdf) · ACM · O 5G NSA deixa o controle com o LTE, então, ao trocar de célula 5G, solta o 5G, passa pelo LTE e conecta de novo: média de 108 ms (4G→5G: 80 ms); logo depois de trocas que envolvem 5G, a vazão TCP cai 73–83% - [5G 통신서비스 품질평가 결과 발표](https://www.korea.kr/briefing/policyBriefingView.do?newsId=156404679) · 과학기술정보통신부 · Segundo um anúncio de 2020, o 5G na Coreia é oferecido no modo NSA, e a migração para SA ainda está em fase de planejamento - [TelephonyDisplayInfo](https://developer.android.com/reference/android/telephony/TelephonyDisplayInfo) · Android (Google) · OVERRIDE_NETWORK_TYPE_NR_NSA: indicador de rede quando o aparelho está conectado ao LTE e pode fazer ou já faz conexão dupla (EN-DC) com o 5G (NR) #### hn-captive · Restrições em Wi-Fi público e rede corporativa · Captive portal, restrictive network A página de login do Wi-Fi de um café ou o firewall da empresa bloqueiam a conexão do jogo. - Por quê → Efeito → Na tela: A autenticação na página de login ainda não foi feita, ou o firewall bloqueia as portas do jogo ou o UDP → A própria tentativa de conexão é bloqueada, ou só uma parte passa → Não conecta; o login funciona, mas a entrada no jogo falha - Sintomas: Não conecta / loading infinito / Fatores: Perda de pacotes - Quem: Só eu / Quando: Logo após login ou manutenção - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: avisar o motivo quando a conexão for bloqueada (autenticação na página de login pendente, UDP bloqueado etc.), passar automaticamente para uma rota alternativa se o UDP estiver bloqueado. Servidor: oferecer uma rota alternativa, como TCP 443. - O que fazer (Externo): Orientar os jogadores a fazer primeiro a autenticação na página de login em Wi-Fi público e, em lugares bloqueados como redes corporativas, a usar outra rede. - No gráfico: Alto só em alguns (Falhas de conexão (por rede)) - Onde olhar: Pedir ao jogador que falhou para tentar conectar por outra rede, como os dados móveis, e ver nos logs de conexão do servidor se o primeiro pacote UDP chegou e se a conexão funciona pela rota alternativa TCP 443 - Confirma se: Falha só em um Wi-Fi específico (café, empresa) e conecta na hora em outra rede. A autenticação na página de login não foi feita, ou só o UDP não chega ao servidor - Descarta se: Falha em qualquer rede: aponta para a conta, o servidor ou “Falha ou lentidão no DNS”. Falha em todo um país ou operadora: “Restrição de UDP e inspeção de pacotes por país ou operadora” - Como verificar: Verificação no ambiente do jogador - Fontes: - [RFC 8952: Captive Portal Architecture](https://www.rfc-editor.org/rfc/rfc8952) · IETF · Portal cativo: rede em que o acesso fica restrito até que se cumpram requisitos como aceitar termos ou se autenticar - [RFC 9308: Applicability of the QUIC Transport Protocol](https://www.rfc-editor.org/rfc/rfc9308) · IETF · Segundo estudos de medição, 3–5% das redes bloqueiam todo o UDP, por isso apps baseados em UDP precisam ter uma rota alternativa por TCP (TLS) ### L4 Conexão de internet (14 causas) #### isp-distance · Atraso de propagação (distância física) · Propagation delay Mesmo a luz percorre só cerca de 200 mil km por segundo na fibra óptica. Um servidor distante é lento, por melhor que seja. - Por quê → Efeito → Na tela: O servidor está longe (servidor no exterior, outro continente) → O tempo de ida e volta cresce com a distância (no mínimo 10 ms a cada 1.000 km) → Input lag constante em todas as ações, desvantagem no registro de acerto - Sintomas: Input lag / Fatores: Latência - Quem: Região ou operadora específica / Quando: Sempre - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de rede (Equipe de infraestrutura), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Apenas atenuar (código não muda as leis da física), oferecer seleção de região para o jogador escolher um servidor próximo, reduzir a desvantagem no registro de acerto com compensação de lag (voltar no tempo). - O que fazer (Equipe de infraestrutura): Servidores/SO: instalar servidores regionais onde há mais jogadores. Rede: instalar pontos de presença (edge) perto dos jogadores, escolher links e rotas com menos desvios. - Números de referência: Seul–Tóquio cerca de 30 ms, Seul–Singapura cerca de 75 ms, Seul–costa oeste dos EUA cerca de 140 ms, Seul–Europa cerca de 230–270 ms (ida e volta, por rotas reais). Quase não há cabos grandes na linha reta até a Europa, então o tráfego dá a volta pelo Sudeste Asiático e por Suez ou pelos EUA, e a latência fica bem maior do que a distância sugere. - No gráfico: Sempre alto desde o início (RTT (por país ou região)) - Onde olhar: Associar um país a cada IP de conexão e ver a distribuição de RTT por país. Medir com ping e traceroute até o servidor a partir de uma VM em uma região de nuvem dessa área ou de probes do RIPE Atlas (escolhidos por país ou ASN) - Confirma se: O RTT de países distantes fica sempre alto, em qualquer horário, e perto do atraso mínimo calculado pela distância (10 ms de ida e volta a cada 1.000 km) e das estatísticas públicas de latência - Descarta se: Muito acima do que a distância explica: aponta para “Roteamento com desvio”. Sobe só à noite: “Congestionamento no peering em horário de pico” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Casos reais: riot-direct-2015 - Fontes: - [ITU-T G.114: One-way transmission time](https://www.itu.int/rec/T-REC-G.114-200305-I/en) · ITU · Valor de planejamento do atraso de propagação na fibra óptica: 5 µs/km (cerca de 200 mil km por segundo, 10 ms de ida e volta a cada 1.000 km) - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Medianas medidas de ida e volta a partir de Seul (Korea Central): Tóquio 30 ms, Singapura 68 ms, oeste dos EUA 124–136 ms, Europa 234–244 ms - [AAE-1 & SMW5 cable cuts impact millions of users across multiple countries](https://blog.cloudflare.com/aae-1-smw5-cable-cuts/) · Cloudflare · O tráfego entre Europa e Ásia passa, em geral, por cabos submarinos que cruzam o Egito (Suez) - [Probe Selection (RIPE Atlas REST API)](https://atlas.ripe.net/docs/apis/rest-api-manual/measurements/creating-measurements/probe-selection/) · RIPE NCC · Nas medições do RIPE Atlas, os probes são escolhidos por país, região, ASN ou bloco de endereços para executar ping e traceroute #### isp-satellite · Internet via satélite (órbita baixa ou geoestacionária) · Satellite internet (LEO, GEO) Na internet via satélite, o sinal precisa ir ao espaço e voltar. Com satélites geoestacionários, só a ida e volta já passa de 0,5 segundo. Satélites de órbita baixa como o Starlink costumam ser rápidos, mas no momento em que a rota é redistribuída a latência oscila e a conexão pode cair por um instante. - Por quê → Efeito → Na tela: Conexão de casa, de um navio ou de um avião por internet via satélite geoestacionário ou de órbita baixa, ou por Wi-Fi de bordo que usa satélite → O satélite geoestacionário fica a cerca de 36.000 km de altitude, então a distância em si já é longa. Na órbita baixa, a rota terminal–satélite–estação terrestre é redistribuída em intervalos curtos, e nesse momento surgem atraso e perda por um instante → Geoestacionário: input lag alto em todas as ações. Órbita baixa: normal na maior parte do tempo, com engasgos e teleporte em intervalos regulares - Sintomas: Input lag, Engasgos, Teleporte / Fatores: Latência, Jitter, Perda de pacotes - Quem: Só eu, Mesma casa, Região ou operadora específica / Quando: Sempre, Em intervalos regulares - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: aumentar automaticamente o buffer de interpolação conforme o jitter, enviar os inputs em duplicidade para aguentar perdas curtas, mostrar a qualidade da conexão. Servidor: considerar a latência dos links via satélite ao definir janelas de tempo e limites da compensação de lag, usar timeouts que não derrubem o jogador por uma lacuna de cerca de 1 segundo. - O que fazer (Externo): Avisar os jogadores de que a internet via satélite pode ter latência alta ou picos periódicos, orientar a usar uma conexão terrestre cabeada em conteúdo competitivo sempre que possível. - Números de referência: Na órbita geoestacionária (36.000 km de altitude), só a travessia do espaço leva 260 ms em cada sentido, então a ida e volta passa de 520 ms (ITU-T G.114). No Starlink, de órbita baixa, os dados oficiais (médias de 15 segundos) indicam mediana de 33 ms no horário de pico nos EUA, e mesmo o pior 1% (p99) fica abaixo de 65 ms (2024). Estudos de medição observaram que a latência muda a cada redistribuição de rota, feita a cada 15 segundos, com quedas curtas de menos de 1 segundo. Em medições de internet de bordo de 2018, a ida e volta nos sistemas via satélite teve média de 750 ms. - No gráfico: Alto só em alguns (RTT e jitter (por ASN do provedor de internet via satélite)) - Onde olhar: Verificar se o ASN do IP de conexão é de um provedor de internet via satélite e ver em gráfico separado a distribuição e a série temporal do RTT dos jogadores desse provedor. Pingar o servidor por alguns minutos seguidos a partir de probes do RIPE Atlas nesse ASN, ou pedir ao jogador que deixe o ping rodando e meça o intervalo entre os picos - Confirma se: Provedores geoestacionários: RTT sempre acima de 500 ms. Provedores de órbita baixa: normalmente dezenas de ms, com o RTT mudando ou quedas curtas a cada 15 s, aproximadamente - Descarta se: Provedor sem satélite com RTT sempre alto: “Atraso de propagação (distância física)” ou “Roteamento com desvio”. Picos irregulares: aponta para o sinal do Wi-Fi ou da rede móvel - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Satélites de órbita baixa ficam perto (um trecho do Starlink leva 1,8–3,6 ms), então a latência normal pode ser parecida com a de uma conexão terrestre. Por outro lado, se o ponto em que a estação terrestre entrega o tráfego à internet (PoP) estiver longe do servidor do jogo, a rota fica mais longa na mesma medida, e passar pelos links a laser entre satélites soma mais latência. Estudos de medição atribuem a oscilação a cada 15 segundos à redistribuição de rotas que acontece no mesmo instante no mundo todo, sem relação com a troca de satélite. No Wi-Fi de bordo, a latência varia muito conforme a tecnologia (satélite ou antenas em terra), e os sistemas que usam satélites geoestacionários têm a mesma ida e volta longa descrita acima. - Fontes: - [ITU-T G.114: One-way transmission time](https://www.itu.int/rec/T-REC-G.114-200305-I/en) · ITU · Valores de planejamento do atraso de propagação em um sentido no trecho via satélite: 12 ms a 400 km de altitude, 110 ms a 14.000 km, 260 ms a 36.000 km (geoestacionário) - [Improving Starlink’s Latency](https://starlink.com/public-files/StarlinkLatency.pdf) · Starlink · Mediana no horário de pico nos EUA de 48,5 ms→33 ms, pior 1% (p99) de mais de 150 ms→menos de 65 ms (2024), propagação em um trecho de satélite de 1,8–3,6 ms, passar pelos links a laser soma latência, e a distância da estação terrestre até o ponto de acesso à internet (PoP) também pesa - [A Multifaceted Look at Starlink Performance (WWW 2024)](https://www.nitindermohan.com/documents/2024/pubs/starlinkWWW2024.pdf) · ACM · O Starlink redistribui as rotas a cada 15 segundos, no mesmo instante no mundo todo; nessas transições a latência e a vazão oscilam e surgem quedas curtas de menos de 1 segundo (sem relação com a troca de satélite); latência no trecho terminal↔satélite↔estação terrestre de cerca de 40 ms - [Mile High WiFi: A First Look at In-Flight Internet Connectivity (WWW 2018)](https://aqualab.cs.northwestern.edu/publication/2018/jrula-www18/) · ACM · 45 horas de medição de internet de bordo: ida e volta média de 200 ms nos sistemas com antenas em terra e de 750 ms nos sistemas via satélite, mediana da taxa de perda de 7% nos sistemas via satélite - [Probe Selection (RIPE Atlas REST API)](https://atlas.ripe.net/docs/apis/rest-api-manual/measurements/creating-measurements/probe-selection/) · RIPE NCC · Nas medições do RIPE Atlas, os probes são escolhidos por país, região, ASN ou bloco de endereços para executar ping e traceroute #### isp-routing · Roteamento com desvio · Suboptimal routing Por causa dos contratos de interconexão entre operadoras, o tráfego até um servidor próximo pode dar uma volta longa. - Por quê → Efeito → Na tela: Sua operadora e a operadora do servidor não têm conexão direta → O tráfego passa por outro país ou outra cidade, o que soma distância e equipamentos no caminho → Só os jogadores de certas operadoras têm ping muito alto - Sintomas: Input lag / Fatores: Latência - Quem: Região ou operadora específica / Quando: Sempre - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de infraestrutura): Conectar com várias operadoras (multihoming), monitorar o ping por operadora para achar as que fazem desvio, negociar ajustes de rota com as operadoras. - O que fazer (Externo): Pedir à operadora que ajuste a rota. - Números de referência: Mesmo dentro do mesmo país, o ping pode ser duas ou três vezes maior conforme a rota. - No gráfico: Sempre alto desde o início (RTT (por operadora/ASN)) - Onde olhar: Comparar o RTT por operadora (ASN) e ver, com traceroute ou mtr a partir de probes do RIPE Atlas na operadora lenta ou dos jogadores, por quais países e cidades a rota passa. Medir IPv4 e IPv6 separadamente (mtr -4, -6) - Confirma se: Na mesma região, só uma operadora fica sempre mais alta e a rota passa por outro país ou por uma cidade distante. Ou só uma família de endereços (IPv4 ou IPv6) fica alta - Descarta se: Todas as operadoras igualmente altas: “Atraso de propagação (distância física)”. Alto só à noite: “Congestionamento no peering em horário de pico” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: As rotas de IPv4 e IPv6 são definidas separadamente, então, para o mesmo servidor, uma delas pode dar uma volta longa e ficar lenta (medição da APNIC de 2016: dentro de uma mesma operadora, apareceram grupos de usuários para quem o IPv6 era 15, 25 ou 75 ms mais lento que o IPv4). Apps com Happy Eyeballs (RFC 8305) usam o que conectar primeiro entre IPv6 e IPv4: tentam o IPv6 antes e, se ele conectar dentro dos 250 ms recomendados, nem tentam o IPv4. Por isso tendem a ficar no IPv6 mesmo quando esse caminho é um pouco mais lento. Se o ping está alto só em uma operadora, meça IPv4 e IPv6 separadamente. - Casos reais: riot-direct-2015 - Fontes: - [Quantifying the Causes of Path Inflation (SIGCOMM 2003)](https://conferences.sigcomm.org/sigcomm/2003/papers/p113-spring.pdf) · ACM · Análise de 65 ISPs: as políticas de peering entre ISPs e o roteamento entre domínios alongam muito as rotas - [The Internet at the Speed of Light (HotNets 2014)](https://conferences.sigcomm.org/hotnets/2014/papers/hotnets-XIII-final111.pdf) · ACM · As rotas reais entre roteadores têm, na mediana, cerca de 1,5 vez a distância em linha reta pela fibra, e há casos em que pacotes entre dois pontos próximos dão a volta pelo outro lado do mundo (hairpinning) - [Probe Selection (RIPE Atlas REST API)](https://atlas.ripe.net/docs/apis/rest-api-manual/measurements/creating-measurements/probe-selection/) · RIPE NCC · Nas medições do RIPE Atlas, os probes são escolhidos por país, região, ASN ou bloco de endereços para executar ping e traceroute - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · -4 e -6 medem a rota só por IPv4 ou só por IPv6 - [RFC 8305: Happy Eyeballs Version 2: Better Connectivity Using Concurrency](https://www.rfc-editor.org/rfc/rfc8305) · IETF · Um endereço ou uma família de endereços (IPv4/IPv6) pode estar bloqueado, quebrado ou lento dependendo da rede; tentar o IPv6 primeiro e esperar os 250 ms recomendados antes da próxima tentativa de conexão - [IPv6 Performance – Revisited](https://blog.apnic.net/2016/08/22/ipv6-performance-revisited/) · APNIC · Comparação dos tempos de ida e volta em IPv6 e IPv4 dos mesmos usuários dual stack: algumas redes de acesso tratam pacotes IPv6 de forma totalmente diferente, e dentro de uma operadora aparecem grupos em que o IPv6 é 15, 25 ou 75 ms mais lento #### isp-peak · Congestionamento no peering em horário de pico · Peak-hour congestion at peering Mais ou menos entre 9 e 11 da noite, o tráfego de vídeo dispara e os links entre operadoras (peering) tendem a congestionar. - Por quê → Efeito → Na tela: Streaming e downloads se concentram à noite → Filas e perda de pacotes nos links de peering → Só à noite, jogadores de certas operadoras têm engasgos e teleporte - Sintomas: Engasgos, Teleporte, Rubber banding / Fatores: Jitter, Perda de pacotes, Latência - Quem: Região ou operadora específica / Quando: Horário de pico à noite - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de infraestrutura): Aumentar as conexões diretas com a operadora afetada, desviar de rotas congestionadas, monitorar perda e ping à noite por operadora. - O que fazer (Externo): Pedir à operadora que amplie a capacidade do link de peering. - No gráfico: Alto só em certos horários (RTT e perda (por operadora)) - Onde olhar: Gráfico de RTT e perda por operadora (ASN) ao longo do dia, e mtr à noite e de dia a partir de probes do RIPE Atlas dessa operadora ou dos jogadores, para achar o trecho onde a perda começa - Confirma se: Só uma operadora tem RTT e perda subindo todo dia, mais ou menos entre 9 e 11 da noite, e no mtr a perda e o atraso seguem do link entre operadoras até o destino - Descarta se: Todas as operadoras sobem juntas: aponta para nossos links ou servidores. Só uma casa piora à noite: “Canal de Wi-Fi congestionado” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Inferring Persistent Interdomain Congestion (SIGCOMM 2018)](https://www.caida.org/catalog/papers/2018_inferring_persistent_interdomain_congestion/inferring_persistent_interdomain_congestion.pdf) · ACM · Congestionamento recorrente em alguns links entre operadoras: a latência sobe todo dia no horário de pico, e a taxa de perda também aumenta nos períodos congestionados - [Probe Selection (RIPE Atlas REST API)](https://atlas.ripe.net/docs/apis/rest-api-manual/measurements/creating-measurements/probe-selection/) · RIPE NCC · Nas medições do RIPE Atlas, os probes são escolhidos por país, região, ASN ou bloco de endereços para executar ping e traceroute #### isp-cable · Falha em cabo submarino ou link internacional · Submarine cable fault Quando um cabo submarino se rompe, o tráfego faz desvios longos por semanas (às vezes meses) até o reparo, e os links que sobram ficam congestionados. - Por quê → Efeito → Na tela: Cabo rompido ou falha de equipamento → O tráfego se concentra nas rotas alternativas longas e nos links que sobraram → Ping disparando e perda de pacotes para quem conecta do exterior, por alguns dias ou semanas - Sintomas: Input lag, Teleporte / Fatores: Latência, Perda de pacotes - Quem: Região ou operadora específica / Quando: Sempre - Responsável principal: Externo (Externo) / Também envolvidos: Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Garantir links por outras rotas, mover o tráfego para eles durante a falha. - O que fazer (Externo): Informar aos jogadores no exterior a causa e a previsão de normalização, pedir ao provedor do link o cronograma de reparo. - No gráfico: Degrau a partir de um momento (RTT (por país no exterior)) - Onde olhar: Achar no gráfico de RTT e perda por país o momento em que subiram, comparar com os resumos de falhas de internet do Cloudflare Radar e os avisos das empresas de cabos submarinos, e verificar com traceroute se a rota passou a dar a volta por outro continente - Confirma se: A partir de certo momento, o RTT de uma região específica no exterior sobe um degrau e fica assim por dias ou semanas, com relatos de falha em cabos no mesmo período. A rota muda para um desvio longo, diferente do normal - Descarta se: Volta ao normal em poucos dias, sem relatos de falha: “Mudança de rota e convergência do BGP” ou trecho da operadora - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [AAE-1 & SMW5 cable cuts impact millions of users across multiple countries](https://blog.cloudflare.com/aae-1-smw5-cable-cuts/) · Cloudflare · O reparo de um cabo submarino exige enviar um navio de reparo e costuma levar de alguns dias a algumas semanas (38 dias no caso de Tonga); rompimentos aumentam a latência e a perda nas rotas Europa–Ásia - [Q2 2024 Internet disruption summary](https://blog.cloudflare.com/q2-2024-internet-disruption-summary/) · Cloudflare · Os cabos do Mar Vermelho danificados em fevereiro de 2024 ainda estavam em reparo em julho (zona de conflito); os rompimentos do EASSy e do Seacom em maio foram reparados em 19 dias - [Q1 2024 Internet disruption summary](https://blog.cloudflare.com/q1-2024-internet-disruption-summary/) · Cloudflare · Os rompimentos de cabos na África Ocidental (14 de março) foram reparados 3–6 semanas depois, e o tráfego foi movido para outros cabos nesse meio-tempo #### isp-bgp · Mudança de rota e convergência do BGP · Route change / BGP convergence Quando as informações de roteamento da internet mudam, pacotes se perdem enquanto as rotas convergem de novo, o que leva de alguns segundos a dezenas de segundos (raramente alguns minutos). - Por quê → Efeito → Na tela: As informações de rota mudam em algum trecho de uma operadora → Por alguns segundos a dezenas de segundos, os pacotes somem ou passam para uma rota nova → A tela trava de repente por alguns segundos e depois o ping muda de patamar (ex.: 40 → 70 ms) - Sintomas: Travamento, Teleporte / Fatores: Perda de pacotes, Latência - Quem: Região ou operadora específica / Quando: Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Externo (Externo) - O que fazer (Equipe de desenvolvimento): Usar timeouts que aguentem quedas curtas (não derrubar na hora uma conexão que ficou alguns segundos parada). - O que fazer (Equipe de infraestrutura): Monitorar rotas (acompanhar mudanças de rota e de ping nos nossos blocos de IP), detectar falhas nos nossos links em até 1 segundo com BFD e fazer o failover (o hold time padrão do BGP é de 90–180 segundos), mover o tráfego para outro link se a rota mudar para um caminho longo e não voltar. - O que fazer (Externo): Pedir à operadora que investigue os trechos da rede dela em que as rotas mudam com frequência. - No gráfico: Degrau a partir de um momento (RTT, rota do traceroute) - Onde olhar: Comparar as rotas do traceroute e do mtr de antes e depois do momento em que o RTT mudou, e ver no RIPEstat BGPlay o histórico de mudanças de rota BGP do nosso bloco de endereços (prefix) - Confirma se: Uma pausa de alguns segundos e, em seguida, o RTT muda de patamar, com updates do BGP e mudança de AS path no mesmo instante - Descarta se: Sem mudança de rota registrada, mas alto só à noite: “Congestionamento no peering em horário de pico”. Só algumas conexões ruins: “Um caminho ECMP com defeito” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Casos reais: cloudflare-2020, meta-2021, cloudflare-dns-2025 - Fontes: - [RFC 4271: A Border Gateway Protocol 4 (BGP-4)](https://www.rfc-editor.org/rfc/rfc4271) · IETF · Valor padrão recomendado do hold time do BGP: 90 segundos (se nenhuma mensagem do vizinho chegar nesse tempo, a sessão é encerrada) - [BGP updates in 2024](https://blog.apnic.net/2025/01/07/bgp-updates-in-2024/) · APNIC · Tempo médio diário até rotas instáveis se estabilizarem de novo: 25–35 segundos (IPv4), 40–50 segundos (IPv6) - [Delayed Internet Routing Convergence (SIGCOMM 2000)](https://conferences.sigcomm.org/sigcomm/2000/conf/paper/sigcomm2000-5-2.pdf) · ACM · Depois de uma falha de rota, a convergência leva até vários minutos, com mais perda e latência nesse intervalo (medição feita em 2000) - [BGPlay (RIPEstat Data API)](https://stat.ripe.net/docs/data-api/api-endpoints/bgplay) · RIPE NCC · Mostra as rotas BGP de um bloco de endereços (prefix) no início do período, os updates do BGP observados nesse período e os AS no caminho #### isp-ecmp · Um caminho ECMP com defeito · ECMP / link bundle member fault Operadoras e data centers mantêm vários caminhos para o mesmo destino e mandam cada conexão por um deles. Se só um caminho falha, só quem caiu nesse caminho continua com lag. - Por quê → Efeito → Na tela: Em um trecho com vários links agregados, um link ou um equipamento está com defeito ou congestionado → O caminho é escolhido pela combinação de endereços e portas (hash), então só as conexões que caem nesse caminho sofrem perda e atraso → Mesma região e mesma operadora, mas só alguns jogadores têm teleporte constante. Às vezes reconectar resolve - Sintomas: Teleporte, Rubber banding, Engasgos / Fatores: Perda de pacotes, Jitter - Quem: Só eu, Região ou operadora específica / Quando: Sempre - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Externo (Externo) - O que fazer (Equipe de desenvolvimento): Registrar estatísticas de perda e retransmissão por conexão, para poder extrair o IP, a porta e o horário de quem é afetado (no TCP, o número de retransmissões do TCP_INFO; no UDP, calcular pelos números de sequência que faltam). - O que fazer (Equipe de infraestrutura): Juntar IP, porta e horário de quem é afetado e repassar à operadora ou ao data center, monitorar a perda por caminho, medir os caminhos com o mesmo protocolo e a mesma porta do jogo (mtr --tcp ou --udp com --port), tirar do grupo o link ou equipamento com defeito se o caminho passar pelos nossos equipamentos. - O que fazer (Externo): Pedir à operadora que verifique e substitua o caminho com defeito, orientar os jogadores a reconectar para contornar o problema por enquanto (quando a reconexão muda a porta). - Números de referência: Com 4 caminhos, só cerca de um quarto dos jogadores é afetado. O teste de ping pode seguir um caminho diferente do jogo e dar resultado normal. - No gráfico: Alto só em alguns (Perda e retransmissões por conexão (por IP e porta)) - Onde olhar: Separar a perda e as retransmissões por conexão por IP e porta de origem. Rodar o mtr em UDP (-u) contra a porta do jogo (-P) com a porta de origem fixa (-L) e repetir várias vezes trocando a porta de origem. Com -P e sem -L, a porta de origem muda a cada requisição e vários caminhos se misturam - Confirma se: Dentro da mesma região e operadora, só certas combinações de porta (ou endereço) de origem têm perda constante, e o problema some quando uma reconexão muda a porta - Descarta se: Ruim com qualquer porta: congestionamento ou falha em um trecho inteiro - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Para não embaralhar a ordem dos pacotes de uma conexão, os equipamentos (ECMP, LAG) fixam cada conexão em um caminho com base em um valor calculado a partir dos endereços e portas (ou só dos endereços, conforme a configuração do equipamento). Onde só os endereços são usados, reconectar cai no mesmo caminho e não ajuda. Por isso, quando chegam juntos reports como “o ping está normal, mas o jogo tem lag” e “reconectei e melhorou”, suspeite desta causa. - Fontes: - [RFC 7424: Mechanisms for Optimizing Link Aggregation Group (LAG) and Equal-Cost Multipath (ECMP) Component Link Utilization in Networks](https://www.rfc-editor.org/rfc/rfc7424) · IETF · LAG e ECMP escolhem um link por fluxo a partir de um hash de campos do cabeçalho, para manter a ordem dos pacotes (muitos fluxos para um link) - [RFC 2991: Multipath Issues in Unicast and Multicast Next-Hop Selection](https://www.rfc-editor.org/rfc/rfc2991) · IETF · O critério que define um fluxo varia conforme a implementação (só o endereço de destino, o par de endereços ou incluindo as portas); com vários caminhos, é difícil confiar nos resultados de ping e traceroute - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · Opções -u (UDP), -P (porta de destino) e -L (porta de origem UDP); só com -P, o número de sequência da requisição vai na porta de origem, que muda a cada requisição #### isp-shaping · Limitação de velocidade e gerenciamento de tráfego da operadora · Traffic shaping, data caps Quando a franquia de dados acaba, ou em planos que gerenciam certos tipos de tráfego, os pacotes são atrasados ou descartados. - Por quê → Efeito → Na tela: Velocidade reduzida depois que a franquia do plano acaba, ou restrição a certos tipos de tráfego → Os pacotes esperam na fila ou são descartados → Lag depois de certo volume de uso, principalmente no celular - Sintomas: Input lag, Teleporte / Fatores: Latência, Perda de pacotes - Quem: Só eu, Região ou operadora específica / Quando: Sempre, Horário de pico à noite - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Reduzir o tráfego do jogo (compressão, enviar só o necessário). - O que fazer (Equipe de infraestrutura): Se o tráfego do jogo é atrasado ou descartado só em uma operadora, reunir evidências e acionar a operadora. - O que fazer (Externo): Orientar os jogadores a verificar se a franquia do plano acabou ou se a velocidade foi reduzida e se outros apps do mesmo celular estão usando dados, perguntar à operadora se ela restringe o tráfego de jogos. - Números de referência: Na Coreia, planos móveis costumam limitar a velocidade a 1–5 Mbps quando a franquia acaba, e planos baratos a centenas de kbps. O jogo em si gasta pouco, mas se outros apps do mesmo celular usam dados, forma-se uma fila na frente do equipamento que limita a velocidade. - No gráfico: Achata ao bater no limite (Vazão, RTT) - Onde olhar: Pedir ao jogador que veja no app da operadora quanto resta da franquia e se a velocidade está reduzida, e que faça um teste de velocidade para ver a velocidade máxima. No servidor, comparar perda e RTT por operadora - Confirma se: A vazão para em um valor fixo, como 1–5 Mbps ou algumas centenas de kbps, e a partir daí o RTT e a perda aumentam quando outros apps do mesmo celular usam dados. Some ao contratar mais dados ou mudar para o Wi-Fi - Descarta se: Sem limitação de velocidade, mas só uma operadora ruim: “Congestionamento no peering em horário de pico” ou “Roteamento com desvio” - Como verificar: Verificação no ambiente do jogador - Fontes: - [SKT, 고객 선택권과 혜택 강화한 신규 5G 요금제 출시](https://news.sktelecom.com/180213) · SK텔레콤 · Exemplos de controle de velocidade depois que a franquia básica de planos 5G acaba: até 400 kbps, 1 Mbps, 3 Mbps - [SKT, 요금제 개편](https://news.sktelecom.com/225487) · SK텔레콤 · O serviço continua com até 400 kbps mesmo depois de acabar a franquia incluída (programa coreano “dados de segurança para todos”) #### isp-udp-block · Restrição de UDP e inspeção de pacotes por país ou operadora · UDP blocking, throttling and inspection by networks Algumas redes bloqueiam endereços e portas UDP específicos ou limitam a velocidade do UDP, e equipamentos de inspeção de pacotes filtram protocolos que não reconhecem. Jogos que se comunicam por UDP não conectam nessas redes ou caem com frequência. - Por quê → Efeito → Na tela: Conexão a partir de redes de operadoras que limitam a velocidade do UDP ou de redes com equipamentos de inspeção de tráfego (censura) em nível de país ou operadora → Endereços e portas UDP específicos são bloqueados, o UDP é limitado nos horários de pico, portas ou protocolos fora de uma lista de permissões são filtrados, ou só os primeiros pacotes passam antes do bloqueio → Só jogadores de certos países ou operadoras: não conecta ou fica em loading infinito, desconexão logo depois de conectar, teleporte por perda de pacotes nos horários de pico - Sintomas: Não conecta / loading infinito, Desconexão, Teleporte / Fatores: Perda de pacotes - Quem: Região ou operadora específica / Quando: Logo após login ou manutenção, Sempre, Horário de pico à noite - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Desenvolvimento do servidor (Equipe de desenvolvimento), Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Cliente: mudar automaticamente para um caminho alternativo por TCP/TLS 443 se o UDP não conectar em alguns segundos, detectar também conexões que caem logo depois de conectar e tentar de novo pelo caminho alternativo, registrar no log por qual caminho conectou. Servidor: aceitar o mesmo protocolo do jogo também por TCP 443 (TLS), ajustar os timeouts porque o caminho alternativo pode ter mais latência. - O que fazer (Equipe de infraestrutura): Antes de lançar em um novo país, medir nas redes das operadoras locais se o UDP chega e qual é a perda no horário de pico, colocar perto da região relays ou gateways que aceitem o caminho alternativo por TCP 443, monitorar as taxas de sucesso de conexão UDP e TCP por país e ASN, reunir evidências e acionar as operadoras em que a limitação de UDP for confirmada. - O que fazer (Externo): Perguntar à operadora ou ao órgão responsável quais são os critérios de restrição de UDP e se é possível flexibilizar, orientar os jogadores a conectar de outra rede para comparar. - Números de referência: Segundo medições citadas em um documento do IETF, 3–5% das redes bloqueiam todo o UDP. Quando o Google analisou o uso do QUIC (baseado em UDP) em 2016, 4,4% dos clientes não conseguiam usá-lo porque o UDP ou o QUIC estava bloqueado ou o MTU do caminho era pequeno; a maioria estava atrás de firewalls corporativos, e não se viu nenhum caso de uma operadora inteira bloqueando. Outros 0,3% estavam em redes em que a perda aumentava muito no horário de pico, aparentemente por limitação de UDP; o Google reduziu esse número de 1% em 2015 com pedidos às operadoras. - No gráfico: Alto só em alguns (Taxa de sucesso de conexão UDP (por país/ASN)) - Onde olhar: Separar por país e ASN a taxa de sucesso de conexão UDP e a do caminho alternativo por TCP 443. A partir de uma VM de nuvem ou do PC de um jogador na rede dessa operadora, testar a conexão na porta UDP do jogo e no TCP 443 separadamente, e comparar mtr -u -P (porta do jogo) com mtr -T -P 443 para ver a partir de qual trecho as respostas somem - Confirma se: Só em um país ou ASN específico, o UDP não recebe a primeira resposta ou cai em poucos segundos, enquanto o TCP 443 funciona do mesmo lugar. Se for limitação de velocidade, a perda de UDP sobe claramente só no horário de pico, e o TCP é menos afetado - Descarta se: O TCP também falha: aponta para falha de rota, bloqueio de IP ou “Falha ou lentidão no DNS”. Igual em todos os países: configuração do nosso servidor ou firewall. Perda só em momentos de muito volume, tanto em UDP quanto em TCP: “Descarte do excedente pelo policer” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Segundo um documento de levantamento do IRTF, equipamentos de inspeção de pacotes podem selecionar fluxos UDP por endereço, porta e protocolo e bloqueá-los, ou bloquear tudo menos os protocolos permitidos (lista de permissões). Se o equipamento decide olhando só alguns campos do pacote, uma pequena mudança no protocolo já pode causar bloqueio. No início do QUIC, um firewall deixava passar os primeiros pacotes depois que 1 bit do cabeçalho mudou e bloqueava os seguintes, e a lógica do cliente de voltar para o TCP nunca chegou a ser acionada. Ao lançar em um novo país, isso pode aparecer em reports como “na Coreia funciona, mas em algumas operadoras daquele país não conecta”. Se o bloqueio acontece só na rede de um local, como um café ou um escritório, veja o verbete “Restrições em Wi-Fi público e rede corporativa”. - Fontes: - [RFC 9308: Applicability of the QUIC Transport Protocol](https://www.rfc-editor.org/rfc/rfc9308) · IETF · Estudos de medição mostram que 3–5% das redes bloqueiam todo o UDP, então apps baseados em UDP precisam aceitar falhas de conexão ou ter um caminho alternativo por TCP (TLS); firewalls podem bloquear portas não associadas a um serviço registrado - [The QUIC Transport Protocol: Design and Internet-Scale Deployment (SIGCOMM 2017)](https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/46403.pdf) · ACM · 2016: 4,4% dos clientes não conseguiam usar QUIC sobre UDP (UDP/QUIC bloqueado ou MTU do caminho pequeno, principalmente atrás de firewalls corporativos; nenhum bloqueio de uma operadora inteira foi observado), 0,3% estavam em redes que pareciam limitar o UDP (mais perda no horário de pico; caiu de 1% em 2015 depois de pedidos às operadoras), e um firewall que deixava passar só os primeiros pacotes depois da mudança de 1 bit do cabeçalho e bloqueava o resto, anulando a lógica de voltar para o TCP - [RFC 9505: A Survey of Worldwide Censorship Techniques](https://www.rfc-editor.org/rfc/rfc9505) · IRTF · Equipamentos de inspeção na rede podem selecionar e bloquear fluxos TCP e UDP por endereço, porta e protocolo (já se observou bloqueio de endpoints UDP no QUIC); permitir só os protocolos aprovados leva a bloqueio excessivo, e a limitação de velocidade de tráfegos específicos também é usada - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · Envia UDP com -u ou TCP SYN com -T e define a porta de destino com -P, para medir a rota com o mesmo protocolo e a mesma porta do jogo #### isp-line · Qualidade ruim da linha · Faulty last-mile line / modem Mau contato nos conectores, fiação velha ou defeito no modem causam perda de pacotes constante e quedas periódicas da conexão. - Por quê → Efeito → Na tela: Cabo danificado, mau contato, defeito no modem ou no terminal óptico (ONT) → Pacotes descartados por erros de bit; de vez em quando a conexão cai por alguns segundos a cerca de 1 minuto enquanto reconecta → Perda pequena e constante, de vez em quando travamentos de alguns segundos ou desconexão - Sintomas: Teleporte, Travamento, Desconexão / Fatores: Perda de pacotes - Quem: Mesma casa / Quando: Aleatoriamente, de vez em quando - Responsável principal: Externo (Externo) - O que fazer (Externo): Orientar os jogadores a verificar se outros jogos e chamadas de vídeo também caem e, se caírem, a pedir uma vistoria da linha à operadora. - No gráfico: Picos aleatórios (Taxa de perda, registro de reconexões da linha) - Onde olhar: Medir por alguns minutos, com pathping (ou mtr), a perda até o primeiro trecho da operadora, e ver os horários de reconexão no registro da conexão de internet (WAN) na página de configuração do roteador - Confirma se: Há perda constante desde o primeiro trecho da operadora mesmo com a linha ociosa, e os horários de reconexão no registro do roteador coincidem com os travamentos e as quedas. Outros jogos e chamadas de vídeo também caem - Descarta se: A perda começa no trecho sem fio até o roteador: “Interferência e sinal fraco no Wi-Fi”. Começa em um trecho distante da operadora: rota da operadora - Como verificar: Verificação no ambiente do jogador - Fontes: - [RFC 3635: Definitions of Managed Objects for the Ethernet-like Interface Types](https://www.rfc-editor.org/rfc/rfc3635) · IETF · Frames que não passam na verificação (FCS) são contados como erros de FCS (dot3StatsFCSErrors) e somados aos erros de entrada (ifInErrors) - [Understanding and Mitigating Packet Corruption in Data Center Networks (SIGCOMM 2017)](https://www.microsoft.com/en-us/research/wp-content/uploads/2017/06/CorrOpt_SIGCOMM2017.pdf) · ACM · As principais causas de pacotes corrompidos são transceptores ópticos com defeito, fibra danificada, conectores sujos e instalação malfeita; a perda por corrupção é constante, independentemente da utilização - [pathping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/pathping) · Microsoft · Envia pings a cada trecho por um tempo e calcula a taxa de perda por roteador e por link, mostrando em qual trecho a perda acontece #### isp-dns · Falha ou lentidão no DNS · DNS failure / slowness Se o DNS, que traduz nomes de servidor em endereços, está lento ou falha, o jogo não encontra os servidores de login e de patch. - Por quê → Efeito → Na tela: Falha ou erro de configuração no DNS da operadora → O endereço do servidor de login ou de patch não é encontrado → Espera longa depois de clicar em conectar, ou não conecta. Quem já está conectado não é afetado - Sintomas: Não conecta / loading infinito / Fatores: Latência, Perda de pacotes - Quem: Região ou operadora específica, Só eu / Quando: Logo após login ou manutenção - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Fazer cache de endereços (lembrar o último endereço de servidor que conectou com sucesso), preparar vários DNS (se um falhar, consultar outro). - O que fazer (Externo): Orientar os jogadores a trocar o DNS por outro, como um DNS público. - No gráfico: Alto só em alguns (Falhas de login (por operadora), tempo de consulta DNS) - Onde olhar: Consultar o nome do servidor de login no DNS da operadora e em um DNS público, separadamente, com Resolve-DnsName -Server (ou nslookup) e comparar o tempo de resposta e o resultado - Confirma se: Só o DNS da operadora não responde ou demora, e trocando para um DNS público conecta na hora. Quem já está conectado não é afetado - Descarta se: Qualquer DNS devolve o endereço na hora, mas não conecta: aponta para rota, firewall ou servidor - Como verificar: Verificação no ambiente do jogador - Casos reais: meta-2021, cloudflare-dns-2025, aws-2025 - Fontes: - [Cloudflare 1.1.1.1 Incident on July 14, 2025](https://blog.cloudflare.com/cloudflare-1-1-1-1-incident-on-july-14-2025/) · Cloudflare · Quando um resolvedor DNS público parou por 62 minutos, os usuários que não conseguiam mais resolver nomes ficaram, na prática, sem acesso a qualquer serviço de internet - [RFC 8767: Serving Stale Data to Improve DNS Resiliency](https://www.rfc-editor.org/rfc/rfc8767) · IETF · Continuar usando registros de cache expirados quando não dá para alcançar os servidores autoritativos, para atravessar a falha (serve-stale) - [Resolve-DnsName](https://learn.microsoft.com/en-us/powershell/module/dnsclient/resolve-dnsname) · Microsoft · Resolve um nome no servidor DNS definido com -Server - [nslookup](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/nslookup) · Microsoft · Comando que consulta um nome diretamente em um servidor DNS #### isp-ddos-path · Links compartilhados saturados por DDoS · DDoS saturating shared links Ataques volumosos contra a empresa do jogo, ou contra outro alvo na mesma rede, lotam os links compartilhados. - Por quê → Efeito → Na tela: Grande volume de tráfego de ataque → O tráfego legítimo que usa os mesmos links também é atrasado e descartado → Teleporte, desconexão ou não conecta para muitos jogadores ao mesmo tempo - Sintomas: Teleporte, Desconexão, Não conecta / loading infinito / Fatores: Perda de pacotes, Latência - Quem: Servidor inteiro, Região ou operadora específica / Quando: Aleatoriamente, de vez em quando, Quando junta muita gente - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de infraestrutura): Usar um serviço de proteção contra DDoS, desviar o tráfego durante ataques, esconder os endereços dos servidores (deixá-los atrás dos equipamentos de proteção e não expor o endereço real). - O que fazer (Externo): Se o ataque é contra outro alvo na mesma rede, pedir à operadora que bloqueie mais acima na rede (upstream). - No gráfico: Achata ao bater no limite (Tráfego de entrada no link (bps/pps), descartes na interface) - Onde olhar: Tráfego de entrada e pacotes descartados nas interfaces dos nossos links e equipamentos, junto com o registro de detecção de ataques do serviço de proteção contra DDoS, alinhados aos horários em que as quedas se concentram - Confirma se: O tráfego de entrada encosta na capacidade do link e achata, os descartes aumentam, e no mesmo momento jogadores de várias regiões e operadoras têm teleporte ou desconexão juntos - Descarta se: Os links têm folga, mas só algumas operadoras estão ruins: congestionamento ou problema de rota no trecho da operadora - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Infrastructure layer attacks](https://docs.aws.amazon.com/whitepapers/latest/aws-best-practices-ddos-resiliency/infrastructure-layer-attacks.html) · AWS · Ataques volumosos como reflexão UDP e SYN flood esgotam a capacidade da rede ou prendem recursos de firewalls e load balancers - [Obfuscating AWS resources (BP1, BP4, BP5)](https://docs.aws.amazon.com/whitepapers/latest/aws-best-practices-ddos-resiliency/obfuscating-aws-resources-bp1-bp4-bp5.html) · AWS · Colocar serviços de borda como CloudFront ou um load balancer na frente dos servidores de origem, para reduzir a exposição direta - [RFC 7999: BLACKHOLE Community](https://www.rfc-editor.org/rfc/rfc7999) · IETF · A community BLACKHOLE, anunciada via BGP para pedir às redes vizinhas que descartem o tráfego destinado a um endereço específico #### isp-cgnat · IP compartilhado pela operadora (CGNAT) · Carrier-grade NAT Redes móveis e algumas operadoras fazem vários assinantes dividirem um mesmo IP e apagam em pouco tempo o mapeamento das conexões ociosas. - Por quê → Efeito → Na tela: O equipamento da operadora gerencia a tabela de sessões de uma enorme quantidade de assinantes → Limite da tabela de sessões, timeout de inatividade curto → Desconexão depois de ficar parado, falsos positivos que bloqueiam de uma vez todos que usam o mesmo IP - Sintomas: Desconexão, Não conecta / loading infinito / Fatores: Perda de pacotes - Quem: Região ou operadora específica / Quando: Depois de ficar parado - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Cliente: enviar heartbeats em intervalos de no máximo metade do menor timeout de inatividade (em redes móveis, pode ser de cerca de 30 segundos), sempre a partir do cliente (o mapeamento do CGNAT da operadora só é renovado com certeza por pacotes que saem da rede interna), reconectar automaticamente se cair. Servidor: responder aos heartbeats e encerrar a conexão por conta própria se não receber nenhum por um certo tempo, usar um token de sessão para manter o mesmo jogador quando o mapeamento mudar e o endereço e a porta forem outros, ter cuidado com políticas de bloqueio por IP, porque várias pessoas podem dividir um IP (decidir junto com critérios de conta e de dispositivo). - O que fazer (Equipe de infraestrutura): Ajustar os limites de conexões por IP e de novas conexões por segundo nos firewalls e equipamentos de proteção contra DDoS para os IPs compartilhados das operadoras (elevar o limite ou abrir exceção para os blocos das operadoras móveis). - Números de referência: Em redes móveis, o timeout de inatividade de UDP pode ser de cerca de 30 segundos. - No gráfico: Queda de conexões em massa (Desconexões (timeout de heartbeat), tempo ocioso antes da queda (por operadora)) - Onde olhar: Ver nos logs de conexão quantas contas estão conectadas ao mesmo tempo por IP e de qual operadora (ASN), e juntar por operadora o tempo ocioso das conexões que caíram depois de ficar paradas. No lado do jogador, conferir o endereço de internet (WAN) na página de configuração do roteador - Confirma se: Nos blocos das operadoras móveis, várias contas conectam de um mesmo IP, e o tempo ocioso antes da queda se concentra em valores curtos, por volta de 30–60 segundos. O endereço WAN do roteador está em 100.64.0.0/10 (espaço de endereços compartilhado para o NAT das operadoras) ou é diferente do endereço que o servidor vê - Descarta se: Concentrado em quem usa roteador doméstico, independentemente da operadora: “Expiração do mapeamento NAT” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [A Multi-perspective Analysis of Carrier-Grade NAT Deployment (IMC 2016)](https://www.icir.org/vern/papers/cgn-imc16.pdf) · ACM · Tempos de mapeamento UDP medidos em NATs: 10–200 segundos, 74% de até 1 minuto; mediana dos CGNs de 65 segundos em redes móveis e de 35 segundos em redes fixas - [RFC 6888: Common Requirements for Carrier-Grade NATs (CGNs)](https://www.rfc-editor.org/rfc/rfc6888) · IETF · CGNs precisam permitir limitar o número de portas externas por assinante e a taxa de criação de novos mapeamentos - [RFC 6269: Issues with IP Address Sharing](https://www.rfc-editor.org/rfc/rfc6269) · IETF · Quando muitos dividem um endereço, o bloqueio por IP (penalty box) também bloqueia os outros assinantes desse endereço - [RFC 6598: IANA-Reserved IPv4 Prefix for Shared Address Space](https://www.rfc-editor.org/rfc/rfc6598) · IETF · 100.64.0.0/10 é o bloco de endereços compartilhado usado entre o equipamento de NAT da operadora (CGN) e o roteador do assinante #### isp-vpn · Tráfego via VPN ou redutor de ping · VPN / game accelerator detour Com uma VPN ou um redutor de ping ligado, os pacotes passam pelos servidores intermediários (relays) dessa empresa. Se o relay estiver longe ou congestionado, a conexão pode até ficar mais lenta. - Por quê → Efeito → Na tela: A VPN ou o redutor de ping desvia todos os pacotes do jogo para os servidores de relay → Soma-se a distância até o relay e o congestionamento dele, e os cabeçalhos do túnel reduzem o MTU (o maior tamanho de pacote que dá para enviar de uma vez) → Ping mais alto e perda de pacotes; não conecta quando o endereço do relay é bloqueado junto com todos que o usam - Sintomas: Input lag, Teleporte, Não conecta / loading infinito / Fatores: Latência, Perda de pacotes - Quem: Só eu / Quando: Sempre, Logo após login ou manutenção - Responsável principal: Externo (Externo) / Também envolvidos: Infraestrutura de rede (Equipe de infraestrutura), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Manter os pacotes UDP em até 1.200 bytes (para não fragmentarem mesmo quando os cabeçalhos do túnel reduzem o MTU), considerar nos bloqueios por IP os endereços de relay compartilhados de VPNs e redutores de ping e decidir junto com critérios de conta e de dispositivo. - O que fazer (Equipe de infraestrutura): Com muitos jogadores no exterior, instalar pontos de presença próprios perto deles, verificar as rotas das operadoras com muitos reports de “liguei o redutor de ping e melhorou”. - O que fazer (Externo): Orientar os jogadores a desligar a VPN ou o redutor de ping e comparar. - Números de referência: Um relay próximo soma alguns ms; um desvio por outro país soma de dezenas de ms a mais de 100 ms. - No gráfico: Alto só em alguns (RTT (por jogador), provedor dono do IP de conexão) - Onde olhar: Verificar se o ASN do IP de conexão é de um provedor de VPN, de redutor de ping ou de hospedagem, e pedir ao jogador que desligue a VPN ou o redutor de ping e compare o ping e o traceroute - Confirma se: O RTT e a perda aumentam, ou a conexão é bloqueada, só com a VPN ou o redutor de ping ligado, e o traceroute mostra trechos passando pelo servidor de relay - Descarta se: Sem diferença ao ligar ou desligar: linha ou trecho da operadora. Melhor com a VPN ou o redutor ligado: problema na rota original da operadora (“Roteamento com desvio”, “Congestionamento no peering em horário de pico”) - Como verificar: Verificação no ambiente do jogador - Saiba mais: Por outro lado, quando a rota da operadora é ruim, o redutor de ping pode passar por uma rota melhor e baixar o ping. Reports de “liguei o redutor de ping e melhorou” são uma pista de problema na rota da operadora, como roteamento com desvio ou congestionamento à noite. - Fontes: - [RFC 4459: MTU and Fragmentation Issues with In-the-Network Tunneling](https://www.rfc-editor.org/rfc/rfc4459) · IETF · Problemas de fragmentação e de MTU do caminho que surgem quando os cabeçalhos de encapsulamento de túneis no meio da rede reduzem o tamanho que dá para enviar - [RFC 8899: Packetization Layer Path MTU Discovery for Datagram Transports](https://www.rfc-editor.org/rfc/rfc8899) · IETF · Recomenda 1.200 bytes como tamanho seguro padrão (BASE_PLPMTU) para transportes de datagramas como o UDP - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Latência de ida e volta somada ao passar por um ponto de presença em outro país: Seul–Tóquio 30 ms, Seul–Hong Kong 39 ms, Seul–Singapura 68 ms ### L5 Equipamentos de rede do data center (11 causas) #### dc-firewall · Tabela de sessões do firewall cheia · Firewall session table exhaustion O firewall registra na tabela de sessões cada conexão que deixa passar, para rastreá-la. Quando a tabela enche, ele não aceita novas conexões. - Por quê → Efeito → Na tela: Um pico de conexões ou um ataque leva o número de sessões ao limite → Sem entrada livre para registrar a nova conexão, ela é recusada → Quem tenta entrar não conecta ou fica em loading infinito, e algumas conexões já abertas também sofrem desconexão - Sintomas: Não conecta / loading infinito, Desconexão / Fatores: Perda de pacotes - Quem: Servidor inteiro / Quando: Logo após login ou manutenção, Quando junta muita gente - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: controlar picos de conexão com um sistema de fila de login, reutilizar conexões para não abrir conexões curtas repetidamente, encerrar por conta própria as conexões cujo heartbeat parou (para conexões mortas não ocuparem a tabela de sessões por muito tempo). Cliente: enviar heartbeats em intervalos de no máximo metade do menor timeout de inatividade, reconectar automaticamente se cair, aumentando o intervalo entre tentativas e espalhando-as aleatoriamente (para não voltarem todos de uma vez). - O que fazer (Equipe de infraestrutura): Aumentar a tabela de sessões, limpar rápido as conexões curtas que já terminaram (reduzir o timeout das sessões encerradas), ao reduzir o timeout de sessões ociosas avisar a equipe de desenvolvimento para ajustar o intervalo de heartbeat, bloquear ataques, criar alerta de utilização da tabela de sessões. - No gráfico: Achata ao bater no limite (Sessões no firewall, falhas de novas conexões) - Onde olhar: Ver em gráfico as sessões simultâneas do firewall junto com o limite de sessões e procurar no log do equipamento descartes por falha ao criar sessão. Em firewall Linux, comparar nf_conntrack_count com nf_conntrack_max e procurar “nf_conntrack: table full, dropping packet” no dmesg; em instância da AWS, ver conntrack_allowance_exceeded no ethtool -S - Confirma se: A partir do momento em que o número de sessões encosta no limite e achata, as falhas de novas conexões aumentam, junto com registros de falha ao criar sessão ou contadores de descarte - Descarta se: Sessões bem abaixo do limite, mas não conecta: “Estouro da fila de conexões (backlog)” ou servidor de login. Só conexões ociosas caem: “Expiração do rastreamento de conexões no grupo de segurança da nuvem” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · Número máximo de entradas da tabela de rastreamento de conexões (nf_conntrack_max), tempo de retenção de conexões em encerramento (TIME_WAIT e FIN_WAIT, padrão de 120 segundos), TCP estabelecido com padrão de 5 dias, número atual de entradas (nf_conntrack_count) - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Ao passar do número de conexões que a instância consegue rastrear, os pacotes de novas conexões são descartados; conexões ociosas podem esgotar a tabela de rastreamento - [Infrastructure layer attacks](https://docs.aws.amazon.com/whitepapers/latest/aws-best-practices-ddos-resiliency/infrastructure-layer-attacks.html) · AWS · Ataques como SYN flood prendem recursos de servidores, firewalls e load balancers - [net/netfilter/nf_conntrack_core.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_conntrack_core.c?h=v6.12) · Linux kernel · Quando a tabela de rastreamento de conexões enche, aparece “nf_conntrack: table full, dropping packet” no log e os pacotes de novas conexões são descartados - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · conntrack_allowance_exceeded: número de pacotes descartados porque a instância passou do limite de rastreamento de conexões, visível com ethtool -S #### dc-ddos · Desvio pela proteção contra DDoS e falsos positivos · DDoS scrubbing latency, false positives Quando o tráfego é desviado para um centro de scrubbing para barrar ataques, a rota fica mais longa, e às vezes jogadores legítimos são tomados por atacantes e bloqueados. - Por quê → Efeito → Na tela: Depois que um ataque é detectado (ou o tempo todo), o tráfego de entrada é desviado para um centro de scrubbing → A rota fica mais longa, e parte dos pacotes legítimos é classificada como ataque → Ping mais alto para todos; só certas regiões ou operadoras não conectam - Sintomas: Input lag, Não conecta / loading infinito, Teleporte / Fatores: Latência, Perda de pacotes - Quem: Servidor inteiro, Região ou operadora específica / Quando: Quando junta muita gente, Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Documentar o padrão de tráfego do jogo (portas, tamanho dos pacotes, pacotes por segundo) e compartilhar com a equipe de infraestrutura, manter os pacotes UDP em até 1.200 bytes. - O que fazer (Equipe de infraestrutura): Criar regras de proteção adequadas ao padrão de tráfego do jogo, usar pontos de scrubbing regionais, reduzir o tamanho dos pacotes TCP nos trechos de túnel (MSS clamping), verificar falsos positivos pela taxa de falha de conexão por região e operadora. - Números de referência: Um ponto de scrubbing no mesmo país soma alguns ms; passar por um ponto em outro país soma 30–100 ms ou mais. Em geral, só o tráfego de entrada faz o desvio, e as respostas do servidor saem direto. Se o tráfego filtrado volta por um túnel, o tamanho máximo que dá para enviar de uma vez (MTU) também diminui, o que pode levar ao problema em que só os pacotes grandes somem. - No gráfico: Degrau a partir de um momento (RTT (ping), taxa de falha de conexão por região/operadora) - Onde olhar: Colocar os registros de início e fim do desvio (scrubbing) e os logs de bloqueio do equipamento ou serviço de proteção na mesma linha do tempo do gráfico de RTT e da taxa de falha de conexão por região e operadora. Na região afetada, verificar com mtr ou traceroute se há um ponto de scrubbing na rota - Confirma se: O RTT sobe um degrau quando o desvio liga, fica nesse patamar e volta quando desliga. Ou aparecem endereços de jogadores legítimos no log de bloqueio, e só essa região ou operadora tem a taxa de falha de conexão subindo - Descarta se: O RTT sobe em horários sem registro de desvio ou bloqueio: “Roteamento com desvio” ou “Mudança de rota e convergência do BGP”. Só os pacotes grandes somem: “MTU incompatível (só os pacotes grandes somem)” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Maximum transmission unit and maximum segment size](https://developers.cloudflare.com/magic-transit/reference/mtu-mss/) · Cloudflare · O tráfego de entrada é entregue depois da filtragem por um túnel GRE (MTU 1.476), e as respostas de saída vão direto para a internet (DSR); recomenda-se limitar o MSS do TCP a no máximo 1.436, senão os pacotes grandes são descartados ou fragmentados - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Latência de ida e volta por localização do ponto de presença: região Seul–Busan 8 ms, Seul–Tóquio 30 ms, Seul–Singapura 68 ms #### dc-lb-idle · Timeout de inatividade do load balancer · Load balancer idle timeout O load balancer apaga conexões ociosas depois de um tempo definido. O jogo continua tratando a conexão como ativa e, de repente, vem a desconexão. - Por quê → Efeito → Na tela: O jogador fica um tempo sem enviar nenhum pacote (janela de chat aberta, AFK) → O load balancer remove a conexão ociosa (padrões comuns de 60–350 segundos) → Desconexão no instante em que o jogador volta a se mexer - Sintomas: Desconexão / Fatores: Perda de pacotes - Quem: Só eu, Servidor inteiro / Quando: Depois de ficar parado - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: enviar heartbeats em intervalos de no máximo metade do menor timeout de inatividade (atrás de um ALB de 60 segundos, no máximo 30 segundos), reconectar automaticamente se cair. Servidor: responder aos heartbeats e encerrar a conexão por conta própria se não receber nenhum por um certo tempo, retomar a sessão com um token de sessão. - O que fazer (Equipe de infraestrutura): Verificar o timeout de inatividade dos load balancers no caminho, compartilhar os valores com a equipe de desenvolvimento e aumentá-los se necessário. - Números de referência: Os padrões são 60 segundos no AWS ALB, 350 segundos para TCP e 120 segundos para UDP no NLB, e 4 minutos para TCP no Azure Load Balancer. Os valores de TCP do ALB e do NLB podem ser alterados, mas os 120 segundos de UDP do NLB não. Quando o tempo acaba, o ALB também fecha a conexão do lado do servidor, enquanto o NLB apaga em silêncio, e o servidor muitas vezes nem fica sabendo. - No gráfico: Queda de conexões em massa (Desconexões, tempo ocioso antes da queda) - Onde olhar: Verificar a configuração de timeout de inatividade dos load balancers no caminho e juntar, para cada conexão que caiu, o tempo entre o último pacote e a queda. No AWS NLB, ver também o TCP_ELB_Reset_Count no CloudWatch (número de RSTs enviados pelo load balancer) - Confirma se: O tempo ocioso das conexões que caíram se concentra logo acima do valor configurado (ALB 60 s, NLB TCP 350 s etc.), e o problema se repete ao ficar parado por mais tempo que isso e depois se mexer. No NLB, o TCP_ELB_Reset_Count sobe nesses horários - Descarta se: Cai independentemente do tempo ocioso: não é esta causa. Concentrado perto de 350 segundos em servidor acessado direto, sem load balancer: “Expiração do rastreamento de conexões no grupo de segurança da nuvem”. No roteador da casa do jogador: “Expiração do mapeamento NAT” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Edit attributes for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/edit-load-balancer-attributes.html) · AWS · Timeout de inatividade do ALB com padrão de 60 segundos (1–4.000 segundos); se a conexão do cliente ou do destino ficar em silêncio por esse tempo, o load balancer fecha a conexão - [Network Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html) · AWS · Timeout de inatividade de TCP do NLB com padrão de 350 segundos (60–6.000 segundos); depois disso ele só para de rastrear e responde com RST se chegarem dados; fluxos UDP fixos em 120 segundos, sem possibilidade de alteração - [Configure load balancer TCP reset and idle timeout](https://learn.microsoft.com/en-us/azure/load-balancer/load-balancer-tcp-idle-timeout) · Microsoft Azure · Timeout de inatividade do Azure Load Balancer com padrão de 4 minutos (4–100 minutos); depois disso não há garantia de manter a sessão; o reset de TCP é uma configuração opcional - [CloudWatch metrics for your Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html) · AWS · TCP_ELB_Reset_Count: número de pacotes RST gerados e enviados pelo load balancer #### dc-cloud-conntrack · Expiração do rastreamento de conexões no grupo de segurança da nuvem · Cloud security group connection tracking timeout O firewall acoplado ao servidor na nuvem (grupo de segurança) também rastreia conexões, e as entradas de rastreamento de conexões ociosas expiram depois de um tempo definido. Mesmo em servidores acessados direto, sem load balancer, o jogador que ficou parado pode sofrer desconexão. - Por quê → Efeito → Na tela: Configuração em que o grupo de segurança rastreia as conexões do jogo (só alguns endereços permitidos, regras de saída restritas, passagem por NLB etc.) → A entrada de rastreamento de uma conexão que ficou ociosa por um tempo expira, e o grupo de segurança descarta em silêncio os pacotes que chegam depois → Depois de ficar ausente, o jogador volta a se mexer, não tem resposta e sofre desconexão. O programa do servidor demora muito para perceber - Sintomas: Desconexão / Fatores: Perda de pacotes - Quem: Só eu, Servidor inteiro / Quando: Depois de ficar parado - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: enviar heartbeats em intervalos de no máximo metade do menor timeout de inatividade (no máximo 175 segundos para 350 segundos em TCP, no máximo 90 segundos para 180 segundos em streams UDP), reconectar automaticamente se cair. Servidor: responder aos heartbeats e encerrar a conexão por conta própria se não receber nenhum por um certo tempo, retomar a sessão com um token de sessão. - O que fazer (Equipe de infraestrutura): Verificar o tempo de rastreamento de conexões da instância (TcpEstablishedTimeout) e aumentá-lo se necessário (no UDP não dá, porque 180 segundos já é o máximo), avaliar uma configuração de grupo de segurança que não gere rastreamento (portas do jogo abertas para todos os endereços, todas as saídas permitidas; conexões que passam por NLB continuam sendo rastreadas), fazer testes de inatividade ao migrar para uma nova geração de instâncias. - Números de referência: Na AWS, tipos de instância Nitro v6 apagam por padrão a entrada de rastreamento de conexões TCP ociosas depois de 350 segundos (5 dias nos outros tipos). No UDP, o padrão é de 180 segundos para fluxos com várias trocas de requisição e resposta (streams) e de 30 segundos para fluxos em um só sentido ou com uma única requisição e resposta. - No gráfico: Queda de conexões em massa (Desconexões, tempo ocioso antes da queda) - Onde olhar: Verificar a configuração do tempo de rastreamento de conexões da instância e as regras do grupo de segurança (se a configuração gera rastreamento) e juntar o tempo ocioso das conexões que caíram. Logo depois da queda, ver no servidor com ss -tnoi se a conexão continua ESTABLISHED, com o timer de retransmissão (timer:(on,…)) rodando e o backoff crescendo - Confirma se: O tempo ocioso das conexões que caíram se concentra logo acima de 350 s no TCP, 180 s em streams UDP ou 30 s em UDP de um só sentido, e o socket do lado do servidor continua ESTABLISHED sem perceber a queda (se o servidor tem dados a enviar, só repete as retransmissões) - Descarta se: Configuração em que o grupo de segurança não rastreia (portas do jogo abertas para todos os endereços, todas as saídas permitidas, sem NLB no caminho): não é esta causa. Com NLB no caminho: comparar os valores com “Timeout de inatividade do load balancer” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Rastreamento de TCP ocioso com padrão de 350 segundos (Nitro v6; 432.000 segundos = 5 dias nos demais), UDP em um só sentido 30 segundos e stream 180 segundos (máximo 180); regras que permitem todos os endereços não são rastreadas; conexões via NLB são sempre rastreadas - [Update the TCP idle timeout for your Network Load Balancer listener](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/update-idle-timeout.html) · AWS · Se o timeout de inatividade do NLB for maior que o tempo de rastreamento de conexões da instância de destino, o lado da instância descarta primeiro o estado da conexão, em silêncio - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · Em -o, timer:(on,…) é o timer de retransmissão; em -i, backoff é quantas vezes a espera de retransmissão dobrou #### dc-nat-gateway · Limite de conexões e portas do gateway NAT na nuvem · Cloud NAT gateway connection / port limits As conexões que servidores em uma sub-rede privada abrem para fora (autenticação da plataforma, pagamentos, APIs externas) passam pelo gateway NAT, que troca o endereço e a porta. Se as conexões simultâneas para o mesmo destino passam do limite de portas do gateway, as novas conexões falham. - Por quê → Efeito → Na tela: Os servidores abrem muitas conexões curtas para o mesmo endereço externo, como autenticação da plataforma ou pagamentos, ou mantêm conexões abertas por muito tempo → O gateway NAT não consegue alocar mais portas de origem para esse destino, e as novas conexões falham → Dentro do jogo está tudo normal, mas só os recursos que chamam serviços externos, como login, pagamento e entrega de recompensas, falham ou demoram (não conecta / loading infinito, ação perdida / rollback) - Sintomas: Não conecta / loading infinito, Ação perdida / rollback / Fatores: Perda de pacotes, Latência - Quem: Só um recurso específico, Servidor inteiro / Quando: Logo após login ou manutenção, Horário de pico à noite, Quando junta muita gente - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Reutilizar conexões com APIs externas (HTTP keep-alive, pool de conexões) e não abrir uma conexão nova a cada requisição, enviar keepalive nas conexões ociosas do pool em intervalos menores que o timeout de inatividade do NAT (350 segundos na AWS) ou fechá-las antes, repetir as tentativas que falham com intervalos crescentes e espalhados aleatoriamente, registrar a taxa de falha e a latência de cada chamada externa. - O que fazer (Equipe de infraestrutura): Adicionar endereços IP ao gateway NAT (o gateway NAT público da AWS aceita por padrão só 2 Elastic IPs, então para mais é preciso pedir aumento de cota), dividir os gateways por zona de disponibilidade e sub-rede, criar alertas para as métricas de falha de alocação de porta (AWS ErrorPortAllocation, Failed no SNAT Connection Count do Azure, OUT_OF_RESOURCES no dropped_sent_packets_count do Google Cloud), no Google Cloud NAT aumentar o mínimo de portas por VM ou usar alocação dinâmica de portas. - Números de referência: O gateway NAT da AWS abre até 55 mil conexões simultâneas para o mesmo destino (IP, porta e protocolo) por endereço IP, e dá para aumentar anexando até 8 IPs. Conexões em silêncio por 350 segundos são apagadas, e pacotes enviados depois por essa conexão recebem RST. O Azure NAT Gateway tem 64.512 portas SNAT por IP público (até 16 IPs). O Google Cloud NAT divide 64.512 portas por IP de NAT entre as VMs, e o mínimo padrão é de 64 portas por VM (alocação estática); com a configuração padrão, uma VM fica limitada, em geral, a 64 conexões simultâneas para o mesmo destino. - No gráfico: Achata ao bater no limite (Conexões simultâneas no gateway NAT, falhas de alocação de porta) - Onde olhar: Colocar lado a lado as métricas do gateway NAT no CloudWatch da AWS, ErrorPortAllocation, ActiveConnectionCount e PacketsDropCount (no Azure, o SNAT Connection Count filtrado pelo estado Failed e o Dropped Packets; no Google Cloud, o dropped_sent_packets_count com reason OUT_OF_RESOURCES), e os horários de falha das chamadas externas do servidor do jogo - Confirma se: O ErrorPortAllocation (no Azure, SNAT Connection Count no estado Failed; no Google Cloud, descartes OUT_OF_RESOURCES) fica acima de 0 nos horários em que as chamadas externas falham, e as falhas se concentram em chamadas para um ou dois destinos muito usados, como servidores de autenticação ou de pagamento - Descarta se: Falhas de alocação de porta em 0, mas o connect do servidor do jogo falha com EADDRNOTAVAIL e o TIME_WAIT está perto do tamanho da faixa de portas efêmeras: “Esgotamento de portas efêmeras em conexões entre servidores”. Conecta, mas só a resposta demora: “Dependência de serviços externos” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: No “Esgotamento de portas efêmeras em conexões entre servidores”, um único servidor fica sem portas efêmeras. Este limite fica no gateway NAT e é compartilhado por todos os servidores atrás dele (o Google Cloud NAT divide por VM). Se só as chamadas externas falham enquanto os servidores ainda têm folga de TIME_WAIT e na faixa de portas efêmeras, a causa é esta. As portas de conexões fechadas também não são reutilizadas na hora para o mesmo destino (o Azure aplica um cooldown, o Google Cloud bloqueia durante o TIME_WAIT), então quanto mais conexões curtas se repetem, mais rápido se chega ao limite. - Fontes: - [NAT gateway basics](https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-basics.html) · AWS · 55 mil conexões simultâneas por endereço IPv4 para o mesmo destino (IP de destino, porta e protocolo), ampliáveis anexando até 8 IPs (gateways NAT públicos têm por padrão 2 Elastic IPs, ampliáveis com pedido de aumento de cota); a largura de banda escala automaticamente de 5 Gbps até 100 Gbps e a vazão, de 1 milhão até 10 milhões de pacotes por segundo, e os pacotes acima desse limite são descartados - [NAT gateway metrics and dimensions](https://docs.aws.amazon.com/vpc/latest/userguide/metrics-dimensions-nat-gateway.html) · AWS · ErrorPortAllocation: número de vezes em que não foi possível alocar uma porta de origem (acima de 0 indica conexões simultâneas demais), ActiveConnectionCount, IdleTimeoutCount (conexões removidas após 350 segundos ociosas), PacketsDropCount - [Troubleshoot NAT gateways](https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-troubleshooting.html) · AWS · Após 350 segundos ociosa, a conexão expira e os envios seguintes recebem RST; recomenda-se keepalive menor que 350 segundos; ao atingir o limite de conexões, adicionar gateways por zona de disponibilidade, adicionar IPs ou reduzir conexões - [Source Network Address Translation (SNAT) with Azure NAT Gateway](https://learn.microsoft.com/en-us/azure/nat-gateway/nat-gateway-snat) · Microsoft Azure · 64.512 portas SNAT por IP público (até 16 IPs); cada conexão para o mesmo destino precisa de uma porta diferente; portas fechadas passam por um cooldown antes de serem reutilizadas para o mesmo destino - [Metrics and alerts for Azure NAT Gateway](https://learn.microsoft.com/en-us/azure/nat-gateway/nat-metrics) · Microsoft Azure · SNAT Connection Count filtrado pelo estado Failed acima de 0 indica possível esgotamento de portas SNAT; Dropped Packets - [IP addresses and ports](https://cloud.google.com/nat/docs/ports-and-addresses) · Google Cloud · 64.512 portas por IP de NAT, tanto para TCP quanto para UDP; mínimo padrão de portas por VM de 64 (alocação estática) ou 32 (alocação dinâmica); o número de portas reservadas para uma VM limita suas conexões simultâneas para o mesmo destino; portas de conexões fechadas não podem ser usadas durante o TIME_WAIT - [Logs and metrics](https://cloud.google.com/nat/docs/monitoring) · Google Cloud · dropped_sent_packets_count com reason OUT_OF_RESOURCES: pacotes descartados por falta de IPs ou portas de NAT #### dc-lb-imbalance · Desbalanceamento do load balancer e health check enganoso · LB imbalance, bad health checks As conexões se concentram em um único servidor, ou jogadores continuam sendo mandados para um servidor que já caiu. - Por quê → Efeito → Na tela: A regra de distribuição não serve para o caso, ou o health check não enxerga o estado real → Só um servidor fica sobrecarregado, ou há tentativas de conexão a um servidor que caiu → Só alguns canais ou alguns jogadores: câmera lenta, não conecta ou loading infinito - Sintomas: Câmera lenta, Não conecta / loading infinito / Fatores: Paralisação, Perda de pacotes - Quem: Local ou canal específico / Quando: Logo após login ou manutenção, Quando junta muita gente - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Implementar um health check que responda às verificações do load balancer com base no estado real do jogo (avanço do tick, conexões com o BD), informar também a carga do servidor. - O que fazer (Equipe de infraestrutura): Trocar o health check por um que confirme respostas reais do jogo, distribuir com base na carga dos servidores, monitorar a diferença de conexões entre servidores. - No gráfico: Alto só em alguns (Conexões e uso de CPU por servidor) - Onde olhar: Sobrepor em um mesmo gráfico o número de conexões (ss -s) e o uso de CPU de cada servidor atrás do load balancer, e comparar o estado de saúde dos destinos no load balancer (na AWS, HealthyHostCount e UnHealthyHostCount no CloudWatch) com o estado real dos servidores do jogo - Confirma se: Só um ou dois servidores têm conexões e CPU muito acima dos outros, ou um servidor com o tick parado continua “saudável” e segue recebendo novas conexões - Descarta se: Conexões iguais entre os servidores, mas só um canal lento: carga dentro desse canal (“Sobrecarga de zona em thread única (hotspot)”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Casos reais: aws-2025 - Fontes: - [Load Balancing in the Datacenter](https://sre.google/sre-book/load-balancing-datacenter/) · Google · Round robin simples deixa o uso de CPU variar em até 2 vezes entre tarefas; distribuição ponderada em que os backends informam sua carga nas respostas e nos health checks; estado lame duck, em que o backend pede para não receber mais requisições - [Health checks for Network Load Balancer target groups](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/target-group-health-checks.html) · AWS · Health check padrão a cada 30 segundos, com remoção após 2 falhas; serviços UDP são verificados com health checks TCP ou HTTP, então recomenda-se configurá-los para refletir o estado real do serviço - [CloudWatch metrics for your Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html) · AWS · HealthyHostCount e UnHealthyHostCount: número de destinos considerados saudáveis e não saudáveis #### dc-microburst · Microburst no switch · Switch microburst drops Quando vários servidores mandam pacotes para milhares de jogadores no mesmo instante, o buffer pequeno da porta do switch onde esse tráfego converge transborda em menos de 1 ms. - Por quê → Efeito → Na tela: Spawn de world boss ou skills em massa, ou ticks de vários servidores coincidindo e enviando tudo de uma vez → Os buffers onde várias portas convergem para uma, ou onde uma porta rápida alimenta uma mais lenta (de centenas de KB a alguns MB por porta), enchem num instante → Parte dos pacotes descartada; muitos jogadores com teleporte ou skills que não saem, ao mesmo tempo - Sintomas: Teleporte, Ação perdida / rollback / Fatores: Perda de pacotes - Quem: Local ou canal específico / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de rede (Equipe de infraestrutura), Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Distribuir o envio de forma uniforme dentro do tick (pacing), defasar um pouco o início do tick de cada servidor. - O que fazer (Equipe de infraestrutura): Rede: usar switches com buffers maiores, distribuir o tráfego (espalhar os servidores por vários switches e portas), monitorar os contadores de descarte por porta do switch. Servidores/SO: limitar a taxa total de envio de cada servidor (shaper tc do Linux). - Números de referência: Uma porta de 10 Gbps envia cerca de 1,25 MB em 1 ms. Se o tráfego de duas portas converge para uma ao mesmo tempo, acumulam-se 1,25 MB a cada 1 ms. Mesmo com utilização média de 10% em 1 segundo, a porta pode transbordar na escala de 1 ms. - No gráfico: Sobe com a carga (Descartes de saída na porta do switch) - Onde olhar: Coletar, no menor intervalo possível, os contadores de descarte de saída (ifOutDiscards, ou output drops conforme o equipamento) das portas do switch ligadas aos servidores e das portas onde esse tráfego converge, e comparar com os horários de spawn de boss e de grandes batalhas. Gráficos de utilização média de 1 segundo ou 1 minuto não mostram isso - Confirma se: A utilização média é baixa, mas os descartes de saída aumentam toda vez que muita gente se junta em um lugar, e nesses momentos vários jogadores reportam teleporte e skills que não saem, ao mesmo tempo - Descarta se: Os descartes aumentam de forma constante nos horários de utilização média alta: “Saturação do link do data center”. Os erros de entrada (CRC) aumentam: “Cabo com defeito ou erros na porta” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [High-Resolution Measurement of Data Center Microbursts (IMC 2017)](https://conferences.sigcomm.org/imc/2017/papers/imc17-final60.pdf) · ACM · Mais de 70% dos bursts em data centers terminam em dezenas de µs; bursts descartam pacotes mesmo em portas com utilização média de cerca de 9% - [Data Center TCP (DCTCP) (SIGCOMM 2010)](https://conferences.sigcomm.org/sigcomm/2010/papers/sigcomm/p63.pdf) · ACM · Switches comuns têm buffers rasos (48 portas compartilham 4 MB, e uma porta usa até cerca de 700 KB); há perda quando vários fluxos convergem para uma porta por um breve instante - [RFC 2863: The Interfaces Group MIB](https://www.rfc-editor.org/rfc/rfc2863) · IETF · ifOutDiscards: número de pacotes descartados sem envio mesmo sem erro, por motivos como liberar espaço no buffer #### dc-uplink · Saturação do link do data center · Uplink saturation Quando distribuição de patches, envio de logs ou backups usam o mesmo link do jogo, o link lota. - Por quê → Efeito → Na tela: Transferências grandes ocupam o mesmo link → Filas e perda aumentam no link → Ping mais alto e teleporte no servidor inteiro - Sintomas: Input lag, Teleporte / Fatores: Latência, Perda de pacotes - Quem: Servidor inteiro / Quando: Em intervalos regulares, Quando junta muita gente - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Rede: priorizar o tráfego do jogo (QoS), separar um link para transferências grandes, criar alerta de utilização do link. Servidores/SO: limitar a velocidade de backups, envio de logs e deploys e rodá-los em horários de pouco movimento. - No gráfico: Achata ao bater no limite (Utilização do link, RTT (ping)) - Onde olhar: Colocar a utilização da interface do link do data center (uplink), calculada com SNMP ifHCInOctets e ifHCOutOctets, e os descartes de saída (ifOutDiscards) na mesma linha do tempo dos horários de backup, deploy e envio de logs - Confirma se: Quando a utilização do link encosta no limite de banda e achata, o RTT e os descartes sobem no servidor inteiro, e esses horários coincidem com as transferências grandes - Descarta se: Utilização por minuto bem abaixo do limite, mas com descartes: “Microburst no switch” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 4594: Configuration Guidelines for DiffServ Service Classes](https://www.rfc-editor.org/rfc/rfc4594) · IETF · Separar em classes de serviço diferentes o tráfego interativo em tempo real, como o de jogos, e as transferências grandes, como backups - [RFC 7567: IETF Recommendations Regarding Active Queue Management](https://www.rfc-editor.org/rfc/rfc7567) · IETF · Quando chega a um equipamento mais tráfego do que ele consegue enviar, formam-se filas, e filas excessivas são uma das principais causas de latência - [RFC 2863: The Interfaces Group MIB](https://www.rfc-editor.org/rfc/rfc2863) · IETF · ifHCInOctets e ifHCOutOctets: bytes recebidos e enviados pela interface (64 bits); ifOutDiscards: pacotes descartados sem envio #### dc-failover · Failover de equipamento de rede · Network device failover Quando um roteador ou firewall falha e o tráfego passa para o equipamento reserva (failover), o jogo trava para todo mundo por alguns segundos. - Por quê → Efeito → Na tela: Troca para o equipamento reserva por falha ou manutenção → A troca leva alguns segundos, e as conexões são reiniciadas se as informações de sessão não estiverem sincronizadas → Travamento para todos os jogadores do servidor ao mesmo tempo, desconexões em massa - Sintomas: Travamento, Desconexão / Fatores: Perda de pacotes - Quem: Servidor inteiro / Quando: Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: usar timeouts que aguentem quedas curtas (alguns segundos), permitir retomar a sessão com um token de sessão ao reconectar depois de uma queda. Cliente: reconectar automaticamente se cair (espalhando aleatoriamente o intervalo entre tentativas para não voltarem todos de uma vez). - O que fazer (Equipe de infraestrutura): Usar redundância que compartilhe o estado das conexões, detectar falhas em até 1 segundo com BFD, testar o failover regularmente. - Números de referência: Cerca de 1–3 segundos se o equipamento detecta a falha na hora. Sem detecção rápida de falhas (BFD), dependendo só dos timers padrão do BGP, a rota pode ficar fora por 90–180 segundos até o equipamento vizinho perceber. - No gráfico: Queda de conexões em massa (Conexões, tráfego total de entrada e saída do servidor) - Onde olhar: Logs de eventos de roteadores e firewalls (troca de papel no VRRP, queda de sessões BFD e BGP, registros de failover) junto com o total de conexões e o tráfego do servidor no mesmo horário - Confirma se: No horário do failover registrado no log do equipamento, o tráfego de todos os servidores atrás dele cai a 0 por alguns segundos, ou as conexões caem todas juntas - Descarta se: Só as conexões de um servidor caem: “Crash do servidor” ou “Problemas de driver ou firmware da NIC”. Logs dos equipamentos limpos, e o servidor parado é uma única VM na nuvem: “Manutenção do host na nuvem e live migration” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 5880: Bidirectional Forwarding Detection (BFD)](https://www.rfc-editor.org/rfc/rfc5880) · IETF · Os mecanismos de Hello dos protocolos de roteamento levam 1 segundo ou mais para detectar uma falha; o BFD foi criado para detectar em menos tempo - [RFC 7938: Use of BGP for Routing in Large-Scale Data Centers](https://www.rfc-editor.org/rfc/rfc7938) · IETF · Contar só com os keepalives do BGP deixa a convergência lenta; encerrar a sessão assim que o link cai detecta a falha em ms e reconverge - [RFC 5798: Virtual Router Redundancy Protocol (VRRP) Version 3 for IPv4 and IPv6](https://www.rfc-editor.org/rfc/rfc5798) · IETF · Anúncios VRRP com padrão de 1 segundo; o equipamento reserva assume o papel quando os anúncios param por mais de cerca de 3 intervalos (pouco mais de 3 segundos na configuração padrão) #### dc-bad-cable · Cabo com defeito ou erros na porta · Bad cable / optics (CRC errors) Com transceptor óptico ou cabo com defeito, uma proporção constante dos pacotes que passam por aquele caminho chega corrompida. - Por quê → Efeito → Na tela: Erros de bit por transceptor óptico ou cabo com defeito → O equipamento descarta em silêncio os pacotes corrompidos → Só alguns servidores ou jogadores que usam aquele caminho têm teleporte ou rubber banding por perda constante - Sintomas: Teleporte, Rubber banding / Fatores: Perda de pacotes - Quem: Local ou canal específico / Quando: Sempre - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Monitorar e criar alertas para os contadores de erro de porta (CRC), trocar peças como transceptores ópticos e cabos, tirar o link problemático e desviar o tráfego até a troca. - No gráfico: Alto só em alguns (Erros de CRC por porta, taxa de perda por servidor/caminho) - Onde olhar: Ver os contadores de CRC nas duas pontas do link. No switch, os erros de FCS (dot3StatsFCSErrors) e de entrada (ifInErrors) da porta; no servidor, o crc em RX errors do ip -s -s link (estatística do kernel rx_crc_errors) - Confirma se: Os erros de CRC de uma porta crescem de forma constante, independentemente do volume de tráfego e do horário, e só os servidores e jogadores que passam por essa porta têm perda - Descarta se: Sem erros de CRC e só os descartes de saída aumentando: congestionamento (“Microburst no switch”, “Saturação do link do data center”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Understanding and Mitigating Packet Corruption in Data Center Networks (SIGCOMM 2017)](https://www.microsoft.com/en-us/research/wp-content/uploads/2017/06/CorrOpt_SIGCOMM2017.pdf) · ACM · Análise de 350 mil links de data center: a corrupção vem de transceptores ópticos com defeito, fibra danificada e conectores sujos; a taxa de corrupção é constante, independentemente da utilização; os links problemáticos são retirados para reparo mantendo caminhos suficientes - [RFC 3635: Definitions of Managed Objects for the Ethernet-like Interface Types](https://www.rfc-editor.org/rfc/rfc3635) · IETF · Contador de falhas na verificação de frame, FCS (dot3StatsFCSErrors); esses erros entram na soma dos erros de entrada (ifInErrors) - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · rx_crc_errors: número de pacotes recebidos com erro de CRC; ip -s -s link mostra os erros por tipo #### dc-mtu · MTU incompatível (só os pacotes grandes somem) · MTU black hole Se o MTU (o tamanho máximo que dá para enviar de uma vez) diminui em algum trecho do caminho e os avisos de pacote grande demais são bloqueados, só os pacotes grandes continuam sumindo. - Por quê → Efeito → Na tela: O MTU diminui em um trecho de túnel ou VPN → Um firewall bloqueia os avisos de pacote grande demais (ICMP), e quem envia nunca fica sabendo → Trava e depois vem a desconexão, só ao abrir telas grandes como o inventário ou a lista de personagens - Sintomas: Travamento, Desconexão, Não conecta / loading infinito / Fatores: Perda de pacotes - Quem: Região ou operadora específica, Só eu / Quando: Ao fazer ações específicas, Logo após login ou manutenção - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Para reduzir direto no servidor, configurar o tamanho máximo de segmento do socket com TCP_MAXSEG (só dividir as mensagens em pedaços menores no código do jogo não evita o problema), manter os pacotes UDP em até 1.200 bytes. - O que fazer (Equipe de infraestrutura): Rede: reduzir o tamanho dos pacotes TCP nos trechos de túnel (MSS clamping), liberar os avisos de pacote grande demais (ICMP) nos firewalls e nas ACLs de rede da nuvem. Servidores/SO: liberar os avisos de pacote grande demais (ICMP) também nos firewalls dos servidores e nos grupos de segurança da nuvem, ligar a sondagem de MTU no kernel do servidor (tcp_mtu_probing=1), uma última rede de segurança que só entra em ação depois que a conexão fica alguns segundos parada. - Números de referência: Normalmente 1.500 bytes, caindo para cerca de 1.400 ao passar por um túnel. - No gráfico: Alto só em alguns (Desconexões por região/operadora, falhas em respostas grandes) - Onde olhar: No PC do jogador afetado, enviar ping ao servidor com a flag de não fragmentar (DF) ligada, variando o tamanho. No Windows, ping /f /l 1472 SERVER_IP; no Linux, ping -M do -s 1472 SERVER_IP (1.472 é o MTU de 1.500 menos 20 bytes do cabeçalho IP e 8 bytes do cabeçalho ICMP). Reduzir o tamanho aos poucos para achar o maior que passa, e verificar se os grupos de segurança e firewalls do lado do servidor permitem o aviso ICMP de pacote grande demais (Fragmentation Needed) - Confirma se: Pings pequenos passam, mas o ping DF de 1.472 bytes falha (sem resposta ou com erro dizendo que é preciso fragmentar), e o maior tamanho que passa é pequeno, por volta de 1.400. Jogadores da mesma região só travam ao abrir telas grandes - Descarta se: O ping DF de 1.472 bytes também passa: não é problema de MTU do caminho. Nem pings pequenos passam: o próprio ICMP está bloqueado, e este método não permite concluir - Como verificar: Verificação no ambiente do jogador - Fontes: - [RFC 2923: TCP Problems with Path MTU Discovery](https://www.rfc-editor.org/rfc/rfc2923) · IETF · Se um firewall bloqueia o ICMP (Fragmentation Needed), a descoberta do MTU do caminho falha e só os pacotes grandes continuam sumindo (black hole); pings e mensagens pequenas funcionam, o que dificulta o diagnóstico - [Maximum transmission unit and maximum segment size](https://developers.cloudflare.com/magic-transit/reference/mtu-mss/) · Cloudflare · MTU do caminho na internet de 1.500, 1.476 ao passar por um túnel GRE; recomenda-se limitar o MSS do TCP a no máximo 1.436 - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · Com tcp_mtu_probing=1, a descoberta do MTU do caminho feita pelo próprio TCP (sondagem de MTU) fica desligada normalmente e só é ligada quando um black hole de ICMP é detectado - [ping(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ping.8.html) · iputils · -M do liga a flag DF e recusa pacotes maiores que o MTU do caminho; -s define o tamanho dos dados (padrão de 56 bytes, mais 8 bytes do cabeçalho ICMP) - [ping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ping) · Microsoft · /f liga a flag DF e serve para achar problemas de MTU do caminho; /l define o tamanho dos dados ### L6 Placa de rede do servidor (9 causas) #### nic-irq · Interrupções da NIC concentradas em um só núcleo · Single-queue NIC / no RSS Se a NIC manda todas as interrupções de chegada de pacote para um único núcleo de CPU, esse núcleo vira gargalo. - Por quê → Efeito → Na tela: Só uma fila de recepção, ou o RSS (que distribui entre vários núcleos) desligado → Um núcleo chega a 100% e não consegue tirar os pacotes a tempo → Perda e atraso no servidor inteiro quando junta muita gente (teleporte, input lag) - Sintomas: Teleporte, Rubber banding, Input lag / Fatores: Perda de pacotes, Latência - Quem: Servidor inteiro / Quando: Quando junta muita gente - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Configurar RSS (distribuição pela NIC) e RPS (distribuição pelo kernel), distribuir as interrupções entre vários núcleos, fazer o UDP considerar também as portas na escolha da fila (rx-flow-hash udp4 sdfn no ethtool -N), separar os núcleos que tratam interrupções dos núcleos da thread de tick do jogo, monitorar o %soft por núcleo. - Números de referência: Um núcleo consegue processar pelo kernel, grosso modo, centenas de milhares de pacotes por segundo, dependendo do tamanho dos pacotes e da configuração. Se, no uso por núcleo, o processamento de recepção (%soft no mpstat) está todo concentrado em um só núcleo, é este o caso. - No gráfico: Achata ao bater no limite (%soft por núcleo, pacotes recebidos por segundo) - Onde olhar: Ver o %soft (proporção de tempo tratando interrupções de software) por núcleo com mpstat -P ALL 1, para qual núcleo vão as interrupções de cada fila da NIC em /proc/interrupts, o número de filas com ethtool -l e os pacotes por fila com ethtool -S (os nomes variam conforme o driver) - Confirma se: Só um núcleo fica com %soft perto de 100% e os outros ociosos, e as interrupções e os pacotes se acumulam em uma fila. A partir daí, os pacotes recebidos por segundo não sobem mais - Descarta se: %soft distribuído por igual entre os núcleos: não é esta causa. CPU ociosa, mas com perda: “Limite de PPS da nuvem excedido” ou “Ring buffer insuficiente” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Mesmo com várias filas, se a maior parte do tráfego vem de poucos endereços, como gateways ou proxies, tudo cai em uma fila só. No UDP, algumas NICs escolhem a fila só pelos endereços na configuração padrão, e o tráfego só se espalha por igual depois de mudar para incluir as portas. - Fontes: - [Scaling in the Linux Networking Stack](https://docs.kernel.org/networking/scaling.html) · Linux kernel · RSS (a NIC distribui entre várias filas de recepção) e RPS (o kernel distribui), com uma interrupção própria por fila espalhada entre vários núcleos; recomenda-se RSS quando o tratamento das interrupções de recepção é o gargalo - [How to receive a million packets per second](https://blog.cloudflare.com/how-to-receive-a-million-packets/) · Cloudflare · Medições em que uma fila de recepção atendida por um único núcleo chegou ao teto em cerca de 350 mil–430 mil pacotes por segundo; caso em que a NIC fazia o hash do UDP só pelo endereço IP e tudo caía em uma fila - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · Opção ethtool -N rx-flow-hash udp4 que inclui as portas (f e n) no hash do UDP - [mpstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/mpstat.1.html) · sysstat · %soft: proporção do tempo de CPU gasto tratando interrupções de software; por núcleo com -P ALL #### nic-ring · Ring buffer insuficiente · RX ring buffer overflow Se o ring buffer, onde a NIC guarda os pacotes por um instante, é pequeno, um pico repentino faz o buffer transbordar e os pacotes são descartados. - Por quê → Efeito → Na tela: O ring buffer fica no valor padrão, que é pequeno (256–2.048 slots, conforme o driver) → Durante um burst, o buffer transborda antes de a CPU tirar os pacotes → Perda só nos momentos de burst (teleporte, skills que não saem). Nenhum rastro nos logs do servidor do jogo - Sintomas: Teleporte, Ação perdida / rollback / Fatores: Perda de pacotes - Quem: Servidor inteiro / Quando: Quando junta muita gente - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Aumentar o ring buffer (ethtool -G), monitorar os contadores de descarte (como rx_missed_errors no ethtool -S; os nomes variam conforme o driver). - Números de referência: Com 1 milhão de pacotes por segundo, 1.024 slots enchem em cerca de 1 ms. Se a CPU atrasar uma única vez nesse intervalo, o buffer transborda. A maioria das NICs permite aumentar para alguns milhares de slots. - No gráfico: Picos aleatórios (Contadores de descarte de recepção da NIC) - Onde olhar: Coletar em intervalos curtos os contadores de descarte de recepção do ethtool -S (rx_missed_errors, rx_fifo_errors etc.; os nomes variam conforme o driver) e o missed do ip -s -s link, e ver com ethtool -g o tamanho atual e o máximo do ring - Confirma se: Os contadores de descarte sobem nos momentos de burst, e o tamanho atual do ring está bem abaixo do máximo. Aumentar o ring reduz os descartes - Descarta se: Contadores de descarte parados, mas com perda: próxima etapa no kernel (“Buffer de socket do kernel insuficiente”) ou trecho de rede. Um núcleo com %soft em 100%: “Interrupções da NIC concentradas em um só núcleo” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Linux Base Driver for Intel(R) Ethernet Network Connection (e1000)](https://docs.kernel.org/networking/device_drivers/ethernet/intel/e1000.html) · Linux kernel · Descritores de recepção (slots do ring) do e1000 com padrão de 256, podendo chegar a 4.096 - [drivers/net/ethernet/intel/ice/ice.h (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/intel/ice/ice.h?h=v6.12) · Linux kernel · Descritores de recepção do driver ice com padrão de 2.048 e máximo de 8.160 - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · Pacotes descartados pelo dispositivo por falta de buffer entram em rx_missed_errors; as estatísticas por driver são vistas com ethtool -S - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · -g mostra o tamanho do ring (atual e máximo), -G altera, -S mostra as estatísticas por driver #### nic-coalesce · Coalescência de interrupções excessiva · Interrupt coalescing Para poupar a CPU, a NIC junta pacotes e avisa uma vez só por lote. Os pacotes chegam atrasados pelo tempo gasto juntando. - Por quê → Efeito → Na tela: A NIC junta pacotes por um certo tempo ou quantidade antes de gerar a interrupção → Os pacotes esperam enquanto o lote se forma → Leve aumento de latência. Normalmente pequeno, mas na casa dos ms se exagerado - Sintomas: Input lag / Fatores: Latência - Quem: Servidor inteiro / Quando: Sempre - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Usar coalescência adaptativa, ajustar os valores para servidores de jogo (ethtool -C). - Números de referência: Normalmente de dezenas a centenas de µs. Em jogos, em geral isso é desprezível, mas uma configuração exagerada pode chegar à casa dos ms. - No gráfico: Sempre alto desde o início (Tempo de ida e volta dentro do mesmo data center) - Onde olhar: Ver a configuração atual de coalescência (adaptive-rx, rx-usecs, rx-frames) com ethtool -c e comparar o tempo de ida e volta do ping até outro servidor do mesmo data center antes e depois de mudar a configuração - Confirma se: rx-usecs está alto (centenas de µs ou mais), e reduzir o valor diminui na mesma medida o tempo de ida e volta dentro do data center - Descarta se: O tempo de ida e volta não muda depois de reduzir: não é esta causa - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Linux Driver for Intel(R) Ethernet Network Connection (e1000e)](https://docs.kernel.org/networking/device_drivers/ethernet/intel/e1000e.html) · Linux kernel · O padrão é a moderação adaptativa de interrupções, com 4.000–20.000 interrupções por segundo (intervalos de 50–250 µs); menos interrupções economizam CPU, mas aumentam a latência - [Linux Base Driver for Intel(R) Ethernet Network Connection (e1000)](https://docs.kernel.org/networking/device_drivers/ethernet/intel/e1000.html) · Linux kernel · RxIntDelay pode atrasar as interrupções de recepção em unidades de 1,024 µs até 65.535 (cerca de 67 ms), e valores maiores aumentam a latência de recepção - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · Configurações adaptive-rx, rx-usecs e rx-frames do ethtool -C #### nic-cloud-pps · Limite de PPS da nuvem excedido · Cloud PPS / bandwidth allowance Cada tipo de instância na nuvem tem limites de pacotes por segundo e de largura de banda, e o excedente é descartado em silêncio. - Por quê → Efeito → Na tela: Com mais jogadores simultâneos, os pacotes por segundo passam do limite da instância → A rede da nuvem descarta o excedente → Teleporte e skills que não saem por perda sem causa aparente. A CPU do servidor tem folga - Sintomas: Teleporte, Ação perdida / rollback / Fatores: Perda de pacotes - Quem: Servidor inteiro / Quando: Quando junta muita gente, Horário de pico à noite - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Externo (Externo) - O que fazer (Equipe de desenvolvimento): Juntar pacotes (as mensagens de um tick em um pacote), evitar mandar pacotes muito pequenos com frequência. - O que fazer (Equipe de infraestrutura): Verificar e criar alertas para os contadores de limite excedido (na AWS, pps_allowance_exceeded, conntrack_allowance_exceeded etc.), usar uma instância maior, evitar o limite de rastreamento de conexões com uma configuração de grupo de segurança que não gere rastreamento. - O que fazer (Externo): Perguntar ao provedor de nuvem os limites de pacotes por segundo e de rastreamento de conexões por tipo de instância. - Números de referência: Os limites variam conforme o tamanho da instância, e muitas vezes o limite de pacotes por segundo não é divulgado. O “até 10 Gbps” das instâncias pequenas é uma velocidade de burst disponível só enquanto houver créditos (normalmente 5–60 minutos), e a velocidade base normal é bem menor. - No gráfico: Achata ao bater no limite (Pacotes por segundo, contadores de allowance excedido) - Onde olhar: Coletar em intervalos curtos os contadores do ENA no ethtool -S (pps_allowance_exceeded, bw_in_allowance_exceeded, bw_out_allowance_exceeded e conntrack_allowance_exceeded) e ver junto com os pacotes por segundo. Também dá para publicar esses contadores com o agente do CloudWatch e criar alarmes - Confirma se: Os contadores de allowance excedido sobem nos horários da perda, e os pacotes por segundo param em um valor fixo. A CPU do servidor tem folga - Descarta se: Contadores de excedente parados: não é esta causa. Um núcleo com %soft em 100%: “Interrupções da NIC concentradas em um só núcleo” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: conntrack_allowance_exceeded indica que a tabela de rastreamento de conexões encheu e novas conexões foram descartadas. Se a tabela tem folga e só as conexões ociosas caem porque o rastreamento expirou, veja o verbete “Expiração do rastreamento de conexões no grupo de segurança da nuvem”. - Fontes: - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · Cada instância tem limites de largura de banda, PPS e rastreamento de conexões, e o excedente vai para uma fila e depois é descartado; contadores pps_allowance_exceeded e conntrack_allowance_exceeded - [Amazon EC2 instance network bandwidth](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-network-bandwidth.html) · AWS · O “até N Gbps” das instâncias com até 16 vCPUs é um burst que gasta créditos de I/O de rede (normalmente 5–60 minutos); quando os créditos acabam, volta à largura de banda base #### nic-saturate · Saturação da largura de banda da NIC · NIC bandwidth saturation Usar uma placa de 1 Gbps ou 10 Gbps no limite faz a fila de transmissão crescer até os pacotes serem descartados. - Por quê → Efeito → Na tela: Mais broadcasts levam o tráfego ao limite da placa → A fila de transmissão cresce e, quando transborda, os pacotes são descartados → Atraso e perda no servidor inteiro (input lag, teleporte) - Sintomas: Input lag, Teleporte / Fatores: Latência, Perda de pacotes - Quem: Servidor inteiro / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Reduzir o tráfego (área de interesse, compressão, enviar só o que mudou). - O que fazer (Equipe de infraestrutura): Fazer upgrade da placa (NIC mais rápida ou, na nuvem, instância maior), criar alerta de utilização da NIC. - No gráfico: Achata ao bater no limite (Volume de transmissão da NIC, descartes na transmissão) - Onde olhar: Comparar o txkB/s e o %ifutil (utilização em relação à velocidade da interface) do sar -n DEV 1 com a velocidade da NIC ou a largura de banda da instância, junto com o TX dropped do ip -s link - Confirma se: O volume de transmissão achata perto da largura de banda da NIC ou da instância, e a partir daí os descartes na transmissão e a latência do servidor inteiro aumentam - Descarta se: Largura de banda com folga: não é esta causa. Muitos pacotes pequenos e perda: “Limite de PPS da nuvem excedido” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · tx_dropped: número de pacotes descartados durante a transmissão por falta de recursos - [Amazon EC2 instance network bandwidth](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-network-bandwidth.html) · AWS · A largura de banda que uma instância pode usar depende do número de vCPUs (tamanho da instância) - [sar(1) — Linux manual page](https://man7.org/linux/man-pages/man1/sar.1.html) · sysstat · rxkB/s, txkB/s e %ifutil (utilização em relação à velocidade da interface) do -n DEV #### nic-noisy · Overhead de virtualização e noisy neighbor · Noisy neighbors in virtualization Quando outras máquinas virtuais no mesmo servidor físico usam muita rede ou CPU, o processamento do servidor do jogo atrasa em momentos irregulares. - Por quê → Efeito → Na tela: Outras VMs no mesmo servidor físico usam muitos recursos → O processamento de pacotes da VM do jogo atrasa em momentos irregulares → De vez em quando surge jitter (variação no intervalo de chegada dos pacotes) sem causa clara, causando engasgos - Sintomas: Engasgos / Fatores: Jitter - Quem: Servidor inteiro / Quando: Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de infraestrutura): Usar hosts dedicados ou instâncias com desempenho garantido, parar e iniciar de novo as instâncias com jitter persistente para movê-las para outro host. - O que fazer (Externo): Reportar o host com problema ao provedor de nuvem. - No gráfico: Picos aleatórios (Jitter no tempo de ida e volta dentro do data center, %steal) - Onde olhar: Pingar continuamente outro servidor no mesmo data center para registrar o jitter do tempo de ida e volta, e comparar, junto com o %steal do mpstat, com outras instâncias da mesma configuração - Confirma se: Só esta instância tem picos irregulares de jitter no tempo de ida e volta ou de %steal, e as outras da mesma configuração ficam estáveis. Parar e iniciar de novo para mover para outro host faz o problema sumir - Descarta se: Todas as instâncias da mesma configuração têm os mesmos picos: não é problema do host. Verificar a carga do servidor do jogo ou o trecho de rede - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [How EC2 instance stop and start works](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/how-ec2-instance-stop-start-works.html) · AWS · Parar e iniciar uma instância quase sempre a move para um novo host (exceto hosts dedicados) - [mpstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/mpstat.1.html) · sysstat · %steal: proporção do tempo em que esta CPU virtual teve de esperar enquanto o hypervisor rodava outras CPUs virtuais #### nic-host-maintenance · Manutenção do host na nuvem e live migration · Cloud host maintenance / live migration Quando o provedor de nuvem faz manutenção em um servidor físico (host), ele move as VMs para outro host (live migration) ou as pausa por um momento. Nesse tempo o servidor inteiro para, e se a pausa for longa as conexões caem. - Por quê → Efeito → Na tela: Por manutenção do host ou previsão de falha, o provedor move a VM para outro host ou a pausa por um instante → Durante a migração, CPU, memória e rede ficam lentas, e no final a VM para completamente por um instante (de menos de 1 segundo a cerca de 30 segundos, conforme o provedor e o método) → Todos no servidor travam ao mesmo tempo e depois vêm avanço rápido e teleporte; se a pausa passar do timeout, desconexões em massa - Sintomas: Travamento, Avanço rápido, Teleporte, Desconexão / Fatores: Paralisação, Perda de pacotes - Quem: Servidor inteiro / Quando: Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Externo (Externo) - O que fazer (Equipe de desenvolvimento): Usar timeouts que aguentem pausas de alguns segundos, limitar quantos ticks o servidor recupera depois de uma pausa, calcular o tempo decorrido com monotonic clock, ter um procedimento que salve o progresso e mova os jogadores para outro servidor ao receber o aviso de manutenção. - O que fazer (Equipe de infraestrutura): Assinar os avisos de manutenção e criar alertas (Google Cloud maintenance-event, eventos programados da AWS e AWS Health, Azure Scheduled Events), ao receber o aviso trocar o servidor com antecedência, em horário de poucos jogadores, ajustar o horário da manutenção quando o provedor permitir (Azure Maintenance Configuration, eventos programados da AWS conforme o tipo), cruzar os registros de manutenção com os registros de incidente. - O que fazer (Externo): Confirmar com o provedor de nuvem o cronograma de manutenção e o alcance do impacto, reportar se a mesma instância pausa repetidamente. - Números de referência: O Google Compute Engine diz que a pausa da live migration costuma ser bem menor que 1 segundo, e durante a pausa o relógio do sistema pode saltar até 5 segundos para a frente. O valor de metadados maintenance-event muda 60 segundos antes da migração (se ele tiver sido consultado pelo menos uma vez antes). No Azure, manutenções que não exigem reboot pausam a VM quase sempre por menos de 10 segundos e raramente (no máximo uma vez a cada 18 meses nos tamanhos de uso geral) por cerca de 30 segundos, e a live migration em geral não passa de 5 segundos. O Azure Scheduled Events avisa dessas pausas (Freeze) com pelo menos 15 minutos de antecedência. Porém, se o hardware do host falhar de repente, a recuperação começa na hora, sem aviso. - No gráfico: Lacuna e depois tudo junto (Pacotes enviados e recebidos pelo servidor, intervalo entre ticks) - Onde olhar: Cruzar o horário da parada com os registros do provedor. Google Cloud: compute.instances.migrateOnHostMaintenance nos logs de auditoria; AWS: eventos programados no describe-instance-status e no AWS Health; Azure: Microsoft.Compute/virtualMachines/liveMigration/action no log de atividades (Activity Log) e o horário em que a métrica de disponibilidade da VM (VmAvailabilityMetric) caiu a 0. Dentro do servidor, ver se as métricas e os logs ficaram vazios durante a parada e se o relógio saltou logo depois (logs de sincronização de horário) - Confirma se: O horário em que o servidor inteiro parou coincide com um horário de manutenção ou migração nos registros do provedor, e todas as métricas e logs dentro do servidor ficam vazios nesses poucos segundos - Descarta se: Não está nos registros do provedor e pausas curtas se repetem com frequência: “CPU steal (máquina virtual)”. Registros de reset da NIC no log do kernel: “Problemas de driver ou firmware da NIC” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: A AWS avisa por eventos programados (scheduled events). system-reboot significa que a instância será reiniciada e movida para um novo host; system-maintenance significa que uma manutenção de rede ou de energia pode afetá-la por um momento. Mesmo que a pausa dure só alguns segundos, os clientes que não receberam ACK dos pacotes enviados ao servidor nesse tempo vão dobrando a espera de retransmissão, então a conexão TCP pode continuar parada por mais tempo depois que a pausa acaba (“RTO do TCP e backoff exponencial”). Quando a VM volta da pausa, o relógio pode saltar e levar a um “Salto do relógio do sistema (step do NTP)”, e o health check do load balancer pode falhar e tirar o servidor de rotação por um tempo. Instâncias que não podem ser movidas (como as instâncias bare metal do Google Cloud) são paradas ou reiniciadas na manutenção. - Fontes: - [Live migration process during maintenance events](https://cloud.google.com/compute/docs/instances/live-migration-process) · Google Cloud · A pausa da live migration costuma ser bem menor que 1 segundo; durante a pausa o relógio do sistema salta até 5 segundos para a frente; durante a migração, o desempenho de disco, CPU, memória e rede cai por um tempo; VMs que não fazem live migration são encerradas na manutenção (instâncias bare metal não têm suporte) - [Query metadata server for maintenance event notices](https://cloud.google.com/compute/docs/metadata/getting-live-migration-notice) · Google Cloud · O valor de metadados maintenance-event muda 60 segundos antes da live migration (se a VM está configurada para live migration e o valor foi consultado pelo menos uma vez depois da última manutenção) - [Monitor and plan for a host maintenance event](https://cloud.google.com/compute/docs/instances/monitor-plan-host-maintenance-event) · Google Cloud · A manutenção deixa um evento de sistema compute.instances.migrateOnHostMaintenance nos logs de auditoria - [Scheduled events for Amazon EC2 instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-instances-status-check_sched.html) · AWS · Tipos de eventos programados (system-reboot reinicia e move para um novo host; system-maintenance indica impacto breve por manutenção de rede ou de energia), avisos por e-mail e AWS Health, verificação com describe-instance-status, horário ajustável conforme o tipo - [Maintenance and updates](https://learn.microsoft.com/en-us/azure/virtual-machines/maintenance-and-updates) · Microsoft Azure · Manutenções sem reboot quase sempre pausam por menos de 10 segundos, raramente (no máximo uma vez a cada 18 meses nos tamanhos de uso geral) por cerca de 30 segundos, e a live migration em geral por até 5 segundos; o relógio é sincronizado automaticamente após a pausa; conexões TCP longas podem cair, ou a recuperação pode demorar mais porque o outro lado retransmite com backoff exponencial os dados enviados à VM pausada; o health check do load balancer marca a VM como não saudável em cerca de 10 segundos; confirmação por Microsoft.Compute/virtualMachines/liveMigration/action no log de atividades e pela VmAvailabilityMetric, que vai a 0 durante a pausa; escolha do horário de aplicação com Maintenance Configuration - [Scheduled Events for Linux VMs in Azure](https://learn.microsoft.com/en-us/azure/virtual-machines/linux/scheduled-events) · Microsoft Azure · Freeze (pausa de alguns segundos; CPU e rede podem parar) é avisado com pelo menos 15 minutos de antecedência; em falhas de hardware do host, a recuperação começa na hora, sem prazo de aviso #### nic-reset · Problemas de driver ou firmware da NIC · NIC hang / reset Quando um bug no driver ou um recurso com mau funcionamento faz a placa parar de responder, todo o tráfego de entrada e saída é interrompido enquanto ela reinicia. - Por quê → Efeito → Na tela: Bug no driver, recurso de offload com mau funcionamento → A NIC para de responder e reinicia (alguns segundos) → Todos naquele servidor travam juntos e depois têm teleporte ou desconexão - Sintomas: Travamento, Desconexão / Fatores: Perda de pacotes - Quem: Servidor inteiro / Quando: Aleatoriamente, de vez em quando, Quanto mais tempo ligado - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Verificar e criar alertas para as mensagens “transmit queue … timed out” e “Link is Down” no log do kernel, atualizar drivers e firmware, desligar o recurso problemático (como um offload). - No gráfico: Lacuna e depois tudo junto (Pacotes enviados e recebidos pelo servidor) - Onde olhar: Procurar com dmesg, no log do kernel, “NETDEV WATCHDOG … transmit queue N timed out”, resets do driver e registros “Link is Down” e “Link is Up”, e ver os pacotes enviados e recebidos pelo servidor nesses horários - Confirma se: No horário da parada, o log do kernel tem timeout da fila de transmissão ou registros de link down/up, e os pacotes enviados e recebidos caem a 0 nesses poucos segundos - Descarta se: Log do kernel limpo e a porta do lado do switch normal: parada no processo do servidor do jogo (“Pausa stop-the-world do GC no servidor”, “Deadlock”) ou “Failover de equipamento de rede” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [net/sched/sch_generic.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/sched/sch_generic.c?h=v6.12) · Linux kernel · Quando uma fila de transmissão para, o watchdog do kernel registra “NETDEV WATCHDOG … transmit queue N timed out” e chama a função de reset do driver - [drivers/net/ethernet/intel/ixgbe/ixgbe_main.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c?h=v6.12) · Linux kernel · O driver ixgbe faz reset do adaptador quando a transmissão fica parada e registra “NIC Link is Down” quando o link cai - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · Opção ethtool -K para desligar os recursos de offload um a um #### nic-offload · Atraso pela espera de agregação GRO/LRO · GRO/LRO batching GRO e LRO são recursos que juntam vários pacotes em um só para reduzir a carga na CPU. Dependendo da configuração, um pacote pequeno do jogo pode esperar um pouco pelo próximo pacote para ser agrupado com ele. - Por quê → Efeito → Na tela: A NIC e o kernel agrupam os pacotes que chegam para processá-los juntos → Com a agregação por hardware (LRO) ou um tempo de espera de agregação configurado, o pacote espera um pouco pelo próximo → Leve aumento de latência (em geral, dezenas de µs ou menos) - Sintomas: Input lag / Fatores: Latência - Quem: Servidor inteiro / Quando: Sempre - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Ajustar para o tráfego do jogo (desligar o LRO, verificar a configuração de tempo de espera da agregação), verificar depois das outras causas, porque o efeito costuma ser pequeno. - No gráfico: Sempre alto desde o início (Tempo de ida e volta dentro do mesmo data center) - Onde olhar: Ver o estado de lro e gro com ethtool -k e o valor de gro_flush_timeout na configuração sysfs do dispositivo, e comparar o tempo de ida e volta de pacotes pequenos dentro do data center antes e depois de mudar - Confirma se: O LRO está ligado ou o gro_flush_timeout está acima de 0, e desligar o LRO ou colocar o gro_flush_timeout em 0 reduz o tempo de ida e volta dos pacotes pequenos - Descarta se: A diferença fica dentro de alguns µs depois da mudança: não é esta causa - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [NAPI](https://docs.kernel.org/networking/napi.html) · Linux kernel · Um gro_flush_timeout alto agrupa mais o processamento, mas gera latência quando a carga é baixa - [Linux Base Driver for the Intel(R) Ethernet 10 Gigabit PCI Express Adapters (ixgbe)](https://docs.kernel.org/networking/device_drivers/ethernet/intel/ixgbe.html) · Linux kernel · O GRO economiza CPU juntando o tráfego recebido em blocos grandes; é uma evolução do LRO - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · Configurações gro e lro on|off do ethtool -K ### L7 SO do servidor (kernel) (14 causas) #### so-backlog · Estouro da fila de conexões (backlog) · Listen backlog / SYN queue overflow Quando dezenas de milhares de jogadores se conectam ao mesmo tempo logo após a manutenção, a fila de conexões (backlog) do kernel transborda e as tentativas de conexão são descartadas. - Por quê → Efeito → Na tela: Assim que a manutenção termina, as conexões chegam mais rápido do que o servidor do jogo consegue aceitá-las com accept → A fila de conexões do kernel (backlog: o menor valor entre o que o código do servidor passou ao listen e o teto do kernel) fica cheia → As tentativas de conexão são descartadas, as novas tentativas se repetem e o jogo não conecta ou fica em loading infinito - Sintomas: Não conecta / loading infinito / Fatores: Perda de pacotes - Quem: Servidor inteiro / Quando: Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: aumentar o valor passado ao listen no código, não deixar a thread que aceita conexões parada fazendo outra coisa, ter um sistema de fila de login. Cliente: aumentar o intervalo entre novas tentativas (espalhando aleatoriamente). - O que fazer (Equipe de infraestrutura): Aumentar o somaxconn do kernel (só tem efeito se o valor do listen no código do servidor também subir), manter os SYN cookies ligados, monitorar o número de estouros (TcpExtListenOverflows no nstat). - Números de referência: O teto do kernel Linux (somaxconn) tem padrão de 4.096 desde a versão 5.4 (antes, 128), mas, se o código do servidor passa um valor menor ao listen, o limite é esse valor. Quando a fila enche, o Linux descarta os pedidos de conexão em silêncio, sem erro. Como o SO do cliente reenvia o pedido algumas vezes, começando 1 s depois, para o jogador isso aparece mais como um carregamento longo do que como “falha na conexão”. Um servidor Windows devolve uma resposta de recusa, e o cliente vê “falha na conexão” na hora. - No gráfico: Pico logo após abrir ou manutenção (Estouros da fila de conexões (ListenOverflows), tentativas de conexão) - Onde olhar: Ver o aumento de TcpExtListenOverflows e TcpExtListenDrops no nstat -az e comparar, com ss -ltn, o Recv-Q (conexões esperando o accept) e o Send-Q (limite do backlog) do socket em escuta - Confirma se: ListenOverflows sobe no horário do pico de conexões, e o Recv-Q do socket em escuta fica colado no valor do Send-Q - Descarta se: ListenOverflows parado: não é esta causa. A conexão se estabelece, mas o carregamento não termina: “Avalanche de logins e queries N+1”. Ninguém mais entra a partir de um número exato de jogadores: “Limite de descritores de arquivo” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [listen(2) — Linux manual page](https://man7.org/linux/man-pages/man2/listen.2.html) · Linux man-pages · Um backlog do listen acima do somaxconn é truncado em silêncio; somaxconn tem padrão de 4.096 (desde a 5.4; antes, 128); com a fila cheia, o pedido pode ser ignorado e fica por conta das novas tentativas do cliente - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_syn_retries: o pedido de conexão (SYN) é reenviado várias vezes, com espera de 1 s antes da primeira retransmissão; tcp_abort_on_overflow vem desligado por padrão (sem resposta de recusa mesmo com estouro); tcp_syncookies vem ligado por padrão - [listen function (winsock2.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen) · Microsoft · No Windows, quando a fila enche, o cliente recebe o erro WSAECONNREFUSED - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtListenOverflows: número de pedidos de conexão (SYN) descartados porque a fila do accept estava cheia; TcpExtListenDrops sobe junto - [net/ipv4/tcp_diag.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Valores Recv-Q e Send-Q do ss: no socket em escuta, as conexões esperando o accept e o limite do backlog; no socket conectado, os bytes que o app ainda não leu e os bytes enviados ainda sem ACK #### so-fd · Limite de descritores de arquivo · File descriptor limit (ulimit) Cada conexão precisa de um descritor de arquivo (fd, o número que o SO atribui a cada arquivo ou socket aberto), e o número de fds que um processo pode abrir é limitado. - Por quê → Efeito → Na tela: O número de jogadores simultâneos chega ao limite de descritores de arquivo do processo → O servidor não aceita novas conexões (Too many open files). Abrir logs e conexões com o BD também falha → A partir de um número exato de jogadores ninguém mais entra: não conecta ou fica em loading infinito - Sintomas: Não conecta / loading infinito / Fatores: Perda de pacotes - Quem: Servidor inteiro / Quando: Logo após login ou manutenção, Quando junta muita gente - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Fechar o socket sem falta ao encerrar a conexão (para evitar vazamento de fd), quando o accept falhar com EMFILE (falta de fd) parar de aceitar conexões por um momento ou aceitar com um fd reserva guardado de antemão e fechar na hora (para não gastar CPU processando sem parar o mesmo aviso de conexão). - O que fazer (Equipe de infraestrutura): Verificar o ulimit e a configuração do serviço (LimitNOFILE do systemd), alertar quando chegar perto do limite. - Números de referência: No Linux, ainda é comum o limite ficar em 1.024 quando o serviço não é configurado à parte. Servidores de jogo costumam subir esse limite para dezenas ou centenas de milhares. O Windows não tem um limite padrão tão baixo. - No gráfico: Achata ao bater no limite (Fds abertos pelo processo, conexões simultâneas) - Onde olhar: Ver o fd-nr (número de descritores de arquivo abertos) do processo do servidor do jogo com pidstat -v e o limite de arquivos abertos em /proc/PID/limits, e procurar falhas do accept (EMFILE, Too many open files) no log do servidor - Confirma se: O número de fds achata no valor do limite, e a partir desse momento o accept falha com EMFILE - Descarta se: Número de fds bem abaixo do limite: não é esta causa. Pedidos de conexão descartados no kernel: “Estouro da fila de conexões (backlog)”. Problema no rastreamento de conexões: “Tabela do conntrack cheia no servidor” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: As conexões não aceitas continuam na fila de conexões (backlog) do kernel. Dependendo do código, o servidor continua recebendo o aviso de “nova conexão” e desperdiça CPU. - Fontes: - [systemd-system.conf(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd-system.conf.5.html) · systemd · O padrão de DefaultLimitNOFILE para serviços é 1024:524288 (limite soft de 1.024) - [accept(2) — Linux manual page](https://man7.org/linux/man-pages/man2/accept.2.html) · Linux man-pages · Quando o processo chega ao limite de fds, o accept falha com EMFILE - [Maximum Number of Sockets Supported](https://learn.microsoft.com/en-us/windows/win32/winsock/maximum-number-of-sockets-supported-2) · Microsoft · O Winsock do Windows limita o número de sockets só pela memória disponível - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · fd-nr do -v: número de descritores de arquivo abertos pelo processo - [proc_pid_limits(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc_pid_limits.5.html) · Linux man-pages · /proc/PID/limits mostra os valores soft e hard dos limites de recursos de cada processo #### so-sockbuf · Buffer de socket do kernel insuficiente · Small socket buffers 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ê → Efeito → Na tela: SO_SNDBUF e SO_RCVBUF no valor padrão ou pequenos demais → 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 → Teleporte (perda no UDP) ou avanço rápido (espera no TCP) - Sintomas: Teleporte, Avanço rápido / Fatores: Perda de pacotes, Paralisação - Quem: Servidor inteiro / Quando: Quando junta muita gente - 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 page](https://man7.org/linux/man-pages/man7/socket.7.html) · Linux 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)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/sock.h?h=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 Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux 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)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/udp.c?h=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)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nomes dos contadores mostrados pelo nstat: RcvbufErrors e SndbufErrors do grupo Udp - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · 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 #### so-context · Excesso de threads e troca de contexto · Thread oversubscription, context switching Com muito mais threads do que núcleos, o SO gasta CPU só para revezar as threads na execução. - Por quê → Efeito → Na tela: Centenas a milhares de threads, por exemplo, uma thread por conexão → Sobem o custo da troca de contexto (troca da thread em execução) e os cache misses → CPU ocupada, mas com pouca vazão e ticks irregulares: engasgos e câmera lenta - Sintomas: Engasgos, Câmera lenta / Fatores: Paralisação, Jitter - Quem: Servidor inteiro / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Ajustar o número de threads ao número de núcleos, usar I/O assíncrono (epoll ou IOCP). - O que fazer (Equipe de infraestrutura): Monitorar o número de trocas de contexto e de threads esperando para rodar (cs e r no vmstat). - Números de referência: Cada troca de contexto custa alguns µs, e mais ainda somando os cache misses que vêm depois. - No gráfico: Sobe com a carga (Trocas de contexto por segundo, threads esperando para rodar) - Onde olhar: Comparar o cs (trocas de contexto por segundo) e o r (processos rodando ou esperando CPU) do vmstat 1 com o número de núcleos, e ver com pidstat -w -t as trocas de contexto voluntárias (cswch/s) e involuntárias (nvcswch/s) por thread do servidor do jogo - Confirma se: Quando o número de jogadores simultâneos sobe, r fica muito acima do número de núcleos, cs dispara junto e há centenas de threads com muitas trocas de contexto involuntárias - Descarta se: r fica no máximo no número de núcleos: não é esta causa. Só as trocas voluntárias estão altas: as threads estão esperando lock ou I/O (“Contenção de lock”, “Arquitetura de I/O bloqueante”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Quantifying The Cost of Context Switch (ExpCS 2007)](https://www.usenix.org/legacy/events/expcs07/papers/2-li.pdf) · ACM · Custo direto da troca de contexto de cerca de 3,8 µs; o custo indireto, somando o efeito no cache, vai de alguns µs a mais de 1.000 µs (no ambiente medido) - [vmstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/vmstat.8.html) · procps-ng · Campos cs (trocas de contexto por segundo) e r (processos rodando ou esperando para rodar) - [I/O Completion Ports](https://learn.microsoft.com/en-us/windows/win32/fileio/i-o-completion-ports) · Microsoft · Processa muito I/O assíncrono com um pool de threads criado de antemão e IOCP, e ajusta o número de threads rodando ao mesmo tempo à concorrência da CPU - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · No -w, cswch/s são as trocas de contexto voluntárias (a thread parou sozinha esperando um recurso) e nvcswch/s, as involuntárias (trocada à força por esgotar a fatia de tempo); -t mostra por thread #### so-steal · CPU steal (máquina virtual) · CPU steal time Enquanto o servidor físico (hypervisor) cede por um momento o tempo de CPU da máquina virtual a outra máquina virtual (CPU steal), o servidor do jogo fica parado. - Por quê → Efeito → Na tela: Outra máquina virtual no mesmo host usa muita CPU → Nossa máquina virtual fica sem rodar por períodos de alguns a dezenas de ms → Picos inexplicáveis no tempo de tick: engasgos e travamento - Sintomas: Engasgos, Travamento / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de infraestrutura): Monitorar a métrica de steal (st no top e no vmstat), usar núcleos ou hosts dedicados, evitar instâncias burstable (que ficam lentas quando os créditos de CPU acabam), parar e iniciar de novo as instâncias com steal alto persistente para movê-las para outro host. - O que fazer (Externo): Reportar ao provedor de nuvem os hosts com steal alto persistente. - No gráfico: Picos aleatórios (%steal, tempo de tick do servidor) - Onde olhar: %steal do mpstat -P ALL 1 no mesmo eixo de tempo do tempo de tick do servidor - Confirma se: O %steal sobe junto nos momentos em que o tick dá pico, e cai depois de parar e iniciar de novo a instância para movê-la para outro host - Descarta se: %steal perto de 0, mas o tick dá picos: causa dentro do servidor do jogo (“Pausa stop-the-world do GC no servidor”, “Contenção de lock”). Em contêiner: “Throttling de CPU em contêiner (cota do CFS)” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [proc_stat(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc_stat.5.html) · Linux man-pages · steal: tempo perdido, em ambiente virtualizado, enquanto outros sistemas operacionais rodavam - [Standard mode for burstable performance instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-performance-instances-standard-mode.html) · AWS · Instâncias burstable gastam créditos para passar do desempenho de referência; quando os créditos acabam, o uso de CPU cai para o nível de referência - [How EC2 instance stop and start works](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/how-ec2-instance-stop-start-works.html) · AWS · Parar e iniciar uma instância quase sempre a move para um novo host - [mpstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/mpstat.1.html) · sysstat · %steal: proporção do tempo em que esta CPU virtual teve de esperar enquanto o hypervisor rodava outras CPUs virtuais #### so-cpu-quota · Throttling de CPU em contêiner (cota do CFS) · Container CPU throttling (CFS quota) Quando o contêiner tem limite de CPU e gasta toda a cota dentro do período definido (em geral 100 ms), ele fica parado à força pelo resto do período (throttling). - Por quê → Efeito → Na tela: Limite de CPU (limit) no contêiner do servidor do jogo, no Kubernetes ou similar → Num pico de cálculo do tick, a cota se esgota e o processo fica parado dezenas de ms até o próximo período → CPU média baixa, mas o tick dá picos periódicos: engasgos e câmera lenta - Sintomas: Engasgos, Câmera lenta / Fatores: Paralisação, Jitter - Quem: Servidor inteiro / Quando: Quando junta muita gente, Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Ajustar o número de worker threads ao limite de CPU (para que o runtime não crie uma thread para cada núcleo do host). - O que fazer (Equipe de infraestrutura): Deixar o limite de CPU com folga ou removê-lo e reservar núcleos dedicados, monitorar o número de throttlings (nr_throttled). - Números de referência: Em um servidor com limite de 2 núcleos, se 8 threads trabalham ao mesmo tempo, a cota do período de 100 ms acaba em 25 ms e o processo fica parado por 75 ms. - No gráfico: Sobe com a carga (Número de throttlings (nr_throttled), tempo de tick do servidor) - Onde olhar: Aumento de nr_throttled e throttled_usec (no cgroup v1, nr_throttled e throttled_time) no cpu.stat do cgroup do contêiner, junto com o tempo de tick do servidor - Confirma se: O uso médio de CPU fica abaixo do limite, mas nr_throttled e throttled_usec não param de subir, e isso coincide com os picos de tick - Descarta se: nr_throttled não sobe: não é esta causa. A própria máquina virtual fica sem CPU: “CPU steal (máquina virtual)” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [CFS Bandwidth Control](https://docs.kernel.org/scheduler/sched-bwc.html) · Linux kernel · Ao esgotar a cota recebida em cada período, as threads param até o próximo período (throttling); período padrão de 100 ms; estatística nr_throttled - [Control Group v2](https://docs.kernel.org/admin-guide/cgroup-v2.html) · Linux kernel · cpu.max tem o formato “$MAX $PERIOD” (cota, período), com padrão “max 100000” (período de 100 ms) - [Resource Management for Pods and Containers](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) · Kubernetes · O limit de CPU do contêiner é um limite rígido que o kernel impõe com throttling de CPU #### so-cstate · Picos de latência pelo gerenciamento de energia do servidor (C-states e ajuste de frequência) · CPU power management latency (C-states, frequency scaling) Núcleos de CPU ociosos entram em estados profundos de economia de energia (C-states) e baixam a frequência para economizar eletricidade. Quando chega um pacote ou dispara um timer, o núcleo leva tempo para despertar e subir a frequência, e isso soma latência ao processamento de pacotes pequenos. - Por quê → Efeito → Na tela: A política de ajuste de frequência do SO (governor) ou a configuração de energia do BIOS permite C-states profundos e frequências baixas → Cada vez que um núcleo ocioso desperta de um estado profundo, ele atrasa até centenas de µs. Se a frequência fica presa num valor baixo, o próprio cálculo do tick fica lento → Em geral imperceptível, mas com muitas chamadas entre servidores o atraso se acumula e vira input lag, pior justamente quando o servidor está vazio. Com a frequência presa num valor baixo, o tick atrasa quando junta muita gente: câmera lenta - Sintomas: Input lag, Câmera lenta / Fatores: Latência, Jitter, Paralisação - Quem: Servidor inteiro / Quando: Sempre, Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Pôr a configuração de energia do BIOS no modo desempenho e o governor do SO em performance (scaling_governor do cpufreq), limitar os C-states profundos nos servidores sensíveis à latência (perfil tuned latency-performance, /dev/cpu_dma_latency do PM QoS, parâmetro de kernel intel_idle.max_cstate), depois da mudança comparar o tempo de ida e volta dentro do mesmo data center, o jitter do tempo de tick e o consumo de energia. - Números de referência: Pela tabela do driver intel_idle do Linux 6.12, o C1 (raso) das CPUs Intel para servidor leva 1–2 µs para despertar, e o C6 (profundo), de 133 µs (Skylake-SP) a 290 µs (Sapphire Rapids). Uma vez só é pouco, mas, se um pedido passa por vários servidores, o atraso se soma em cada um. Quanto maior o tempo ocioso previsto, mais profundo o estado que o kernel escolhe, por isso o efeito aparece mais em servidores vazios, onde os pacotes chegam espaçados. O governor powersave do cpufreq genérico fixa a frequência mais baixa da faixa permitida (o algoritmo de mesmo nome do intel_pstate ajusta conforme a carga). - No gráfico: Sempre alto desde o início (Tempo de ida e volta dentro do mesmo data center, frequência dos núcleos) - Onde olhar: Ver com cpupower monitor a proporção de tempo em cada C-state e a frequência real por núcleo, e conferir name, latency (µs para despertar) e usage de cada state em /sys/devices/system/cpu/cpu0/cpuidle/, o scaling_governor do cpufreq e o perfil atual com tuned-adm active - Confirma se: Com pouca carga, o núcleo passa muito tempo no C-state mais profundo ou a frequência fica presa perto do mínimo, e trocar para o governor performance e C-states rasos reduz o tempo de ida e volta e o jitter dos pedidos pequenos - Descarta se: Diferença de no máximo dezenas de µs depois da mudança: esta causa pode ser ignorada. Picos na casa dos ms: “CPU steal (máquina virtual)” ou outra camada - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Em servidores bare metal no data center, verifique juntas a configuração de energia do BIOS (firmware) e a do SO. Na nuvem, só alguns tipos de instância deixam o SO mudar C-state e frequência; na AWS, o padrão já é desempenho máximo, então na maioria dos casos dá para deixar como está. O perfil tuned latency-performance da família Red Hat põe o governor em performance e, via PM QoS, usa só C-states rasos. Desligar a economia de energia aumenta o consumo, então aplique isso só em servidores sensíveis à latência. - Fontes: - [CPU Idle Time Management](https://docs.kernel.org/admin-guide/pm/cpuidle.html) · Linux kernel · Cada estado de economia de energia tem um tempo para despertar (exit latency) e um tempo mínimo de permanência (target residency), e o estado profundo é escolhido conforme o tempo ocioso previsto; latency, usage e time de cada state no sysfs; estados profundos limitados com PM QoS (/dev/cpu_dma_latency) e intel_idle.max_cstate - [drivers/idle/intel_idle.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/idle/intel_idle.c?h=v6.12) · Linux kernel · Tempo para despertar por C-state das CPUs Intel para servidor: Skylake-SP C1 2 µs, C1E 10 µs e C6 133 µs; Ice Lake C6 170 µs; Sapphire Rapids C1 1 µs e C6 290 µs - [CPU Performance Scaling](https://docs.kernel.org/admin-guide/pm/cpufreq.html) · Linux kernel · Ver e mudar o governor com scaling_governor; performance pede a frequência mais alta da faixa permitida, powersave pede a mais baixa - [intel_pstate CPU Performance Scaling Driver](https://docs.kernel.org/admin-guide/pm/intel_pstate.html) · Linux kernel · O algoritmo powersave do intel_pstate, diferente do governor powersave genérico, ajusta conforme a carga (parecido com schedutil e ondemand) - [Chapter 2. Getting started with TuneD](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/monitoring_and_managing_system_status_and_performance/getting-started-with-tuned_monitoring-and-managing-system-status-and-performance) · Red Hat · O perfil latency-performance desliga recursos de economia de energia, põe o governor em performance e usa PM QoS para ficar só em C-states rasos; tuned-adm active mostra o perfil atual - [tools/power/cpupower/man/cpupower-monitor.1 (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/power/cpupower/man/cpupower-monitor.1?h=v6.12) · Linux kernel · cpupower monitor: estatísticas de frequência e de estados de economia de energia por núcleo - [Processor state control for Amazon EC2 Linux instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/processor_state_control.html) · AWS · Só alguns tipos de instância deixam o SO controlar C-states e P-states, e isso pode ser mudado para reduzir a latência; o padrão é desempenho máximo, adequado à maioria das cargas; o Graviton tem frequência fixa e o SO não a controla #### so-oom · OOM killer · Out-of-memory killer Quando a memória acaba, o Linux escolhe o processo que mais usa memória e o mata à força. Em geral, é o servidor do jogo. - Por quê → Efeito → Na tela: Memória esgotada por vazamento ou pico de uso, ou limite de memória do contêiner atingido → O kernel encerra à força o processo do servidor do jogo → Todos naquele servidor sofrem desconexão ao mesmo tempo, e o progresso recente pode sofrer rollback - Sintomas: Desconexão, Ação perdida / rollback / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Quanto mais tempo ligado, Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Corrigir vazamentos, definir um teto de uso de memória e um procedimento que salva e encerra normalmente quando o uso chega perto dele. - O que fazer (Equipe de infraestrutura): Alertar sobre memória, ajustar o limite de memória do contêiner ao uso real, ajustar a ordem de quem é morto primeiro (oom_score_adj). - Números de referência: O log do kernel (dmesg) registra “Out of memory: Killed process”, e no Kubernetes aparece como OOMKilled. O Windows não tem OOM killer. Lá, o mais comum é a alocação de memória falhar e o servidor cair com erro. - No gráfico: Queda de conexões em massa (Conexões, uso de memória) - Onde olhar: Registro “Out of memory: Killed process” no dmesg, status OOMKilled do pod no Kubernetes ou aumento de oom_kill em memory.events no cgroup v2, cruzados com o horário das desconexões - Confirma se: Há registro do processo do servidor do jogo sendo morto no momento da desconexão em massa, e o uso de memória vinha subindo até o limite logo antes - Descarta se: Sem registro de OOM, mas o processo caiu: ver o log de crash e o core dump em “Crash do servidor” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [mm/oom_kill.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/mm/oom_kill.c?h=v6.12) · Linux kernel · Calcula a pontuação para que o processo que mais usa memória fique com a mais alta (considerando oom_score_adj) e registra “Out of memory: Killed process …” ao encerrar - [Assign Memory Resources to Containers and Pods](https://kubernetes.io/docs/tasks/configure-pod-container/assign-memory-resource/) · Kubernetes · Se o contêiner continua usando memória além do limit, ele é encerrado e o status aparece como OOMKilled - [Pushing the Limits of Windows: Virtual Memory](https://learn.microsoft.com/en-us/archive/blogs/markrussinovich/pushing-the-limits-of-windows-virtual-memory) · Microsoft · No Windows, ao chegar ao limite de commit, as alocações que reservam memória falham, o que pode levar a erros no app ou a falhas do sistema - [Control Group v2](https://docs.kernel.org/admin-guide/cgroup-v2.html) · Linux kernel · oom_kill em memory.events: número de processos mortos pelo OOM killer neste cgroup #### so-reclaim · Pausas por recuperação e compactação de memória · Memory compaction / reclaim stalls (THP) O processo fica parado enquanto o SO compacta a memória para montar páginas grandes (huge pages) ou recupera memória livre. - Por quê → Efeito → Na tela: A memória livre diminui, ou o recurso de páginas grandes (THP) dispara a compactação de memória → A thread que pediu memória espera até a recuperação ou a compactação terminar → Paradas irregulares do servidor (de alguns ms a centenas de ms) - Sintomas: Travamento, Engasgos / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Quanto mais tempo ligado, Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Reduzir alocações grandes durante a execução (reservar na inicialização e reutilizar). - O que fazer (Equipe de infraestrutura): Configurar as páginas grandes (THP) para uso só onde for preciso (madvise), aumentar a reserva de memória livre (vm.min_free_kbytes etc.). - No gráfico: Picos aleatórios (Tempo de tick do servidor, PSI de memória) - Onde olhar: Ver some e full em /proc/pressure/memory (proporção do tempo parado esperando memória) e o aumento de compact_stall em /proc/vmstat junto com o tempo de tick do servidor, e conferir a configuração em /sys/kernel/mm/transparent_hugepage/defrag - Confirma se: A PSI de memória sobe e compact_stall aumenta nos momentos de pico do tick. defrag está em always - Descarta se: PSI e compact_stall parados: não é esta causa. Uso de swap subindo: “Swap” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Transparent Hugepage Support](https://docs.kernel.org/admin-guide/mm/transhuge.html) · Linux kernel · Com defrag=always, quando a alocação de THP falha, o kernel recupera e compacta memória ali mesmo, parando o processo; com madvise, isso só acontece nas regiões que pediram - [Documentation for /proc/sys/vm/](https://docs.kernel.org/admin-guide/sysctl/vm.html) · Linux kernel · min_free_kbytes: reserva mínima de memória livre (watermark) que o kernel mantém - [PSI - Pressure Stall Information](https://docs.kernel.org/accounting/psi.html) · Linux kernel · some (proporção do tempo em que algumas tarefas ficaram paradas esperando memória) e full (proporção do tempo em que todas ficaram paradas) em /proc/pressure/memory #### so-timejump · Salto do relógio do sistema (step do NTP) · Wall-clock jump (NTP step) Quando o relógio do servidor é ajustado alguns segundos para frente ou para trás de uma vez, os timers que dependem do relógio do sistema disparam todos juntos ou ficam parados. - Por quê → Efeito → Na tela: A sincronização de horário ajusta o relógio de uma vez, com um salto grande → Timers disparam todos juntos ou ficam parados, e timeouts são avaliados errado → Buffs e cooldowns errados, desconexão de todos ao mesmo tempo, avanço rápido - Sintomas: Avanço rápido, Desconexão, Ação perdida / rollback / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Calcular tempo decorrido, timeouts e cooldowns com o monotonic clock, que não salta nem volta para trás, usar o wall clock só para exibição e registro. - O que fazer (Equipe de infraestrutura): Ajustar o relógio aos poucos (makestep do chrony só logo após iniciar), monitorar o estado da sincronização de horário (diferença do relógio). - Números de referência: O ntpd corrige de uma vez quando a diferença passa de 0,128 s. Abaixo disso, ajusta aos poucos, num ritmo que leva pouco mais de 30 minutos para eliminar 1 s de diferença. O chrony, muito usado hoje, na configuração recomendada (makestep) só corrige de uma vez algumas vezes logo após iniciar e depois ajusta aos poucos. O relógio também salta quando uma máquina virtual para por um momento e volta. - No gráfico: Picos aleatórios (Disparos de timer e desconexões, registros de ajuste do relógio) - Onde olhar: Procurar nos logs do serviço de sincronização de horário ajustes grandes feitos de uma vez e cruzar com o horário do problema. O chrony registra no syslog os ajustes maiores que o valor de logchange (padrão de 1 s) - Confirma se: Há registro de ajuste do relógio no momento dos buffs e cooldowns errados, da desconexão em massa ou do avanço rápido, e o tamanho do ajuste é parecido com o tamanho do problema - Descarta se: Sem registro de ajuste do relógio: não é esta causa. Em máquina virtual, verificar também se ela parou e voltou (“Manutenção do host na nuvem e live migration”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [ntpd - Network Time Protocol (NTP) daemon](https://www.ntp.org/documentation/4.2.8-series/ntpd/) · Network Time Foundation · Corrige de uma vez quando a diferença passa do limiar de step de 128 ms e ajusta aos poucos quando é menor; a 0,5 ms por segundo, corrigir 1 s leva 2.000 s (cerca de 33 minutos) - [chrony – Frequently Asked Questions](https://chrony-project.org/faq.html) · chrony · Recomenda-se permitir o step só algumas vezes logo após o início, como em makestep 1 3; uma máquina virtual que parou e retomou pode voltar com o horário errado - [clock_gettime(2) — Linux manual page](https://man7.org/linux/man-pages/man2/clock_gettime.2.html) · Linux man-pages · CLOCK_MONOTONIC não é afetado por saltos descontínuos do relógio do sistema e não anda para trás - [chrony.conf(5)](https://chrony-project.org/doc/4.6/chrony.conf.html) · chrony · logchange: ajustes do relógio maiores que este valor (padrão de 1 s) são registrados no syslog #### so-cron · Tarefas agendadas · Cron jobs (log rotation, backup, scans) Compressão de logs, backups e varreduras de segurança que rodam todo dia no mesmo horário ocupam CPU e disco. - Por quê → Efeito → Na tela: Tarefas do SO rodam em horários fixos → Dividem CPU e disco com o servidor do jogo → Engasgos e câmera lenta em horários fixos, como todo dia às 4h da madrugada - Sintomas: Engasgos, Câmera lenta / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Em intervalos regulares - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Espalhar os horários das tarefas, baixar a prioridade (nice, ionice), separar do servidor do jogo (rodar em outro servidor). - No gráfico: Picos em intervalos regulares (Uso de CPU, fila do disco, tempo de tick do servidor) - Onde olhar: Levantar os horários das tarefas agendadas com crontab e systemctl list-timers, e ver com pidstat -u -d qual processo usa CPU e disco no momento do pico de tick - Confirma se: O tick dá pico todo dia (ou toda hora) no mesmo horário, e nesse horário um processo de tarefa agendada ocupa CPU e disco - Descarta se: Picos que não caem no mesmo horário todo dia: não é esta causa. Picos a cada alguns segundos ou minutos: “Pausa stop-the-world do GC no servidor”, “Timers disparando todos ao mesmo tempo” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [ionice(1) — Linux manual page](https://man7.org/linux/man-pages/man1/ionice.1.html) · util-linux · Tarefas da classe idle só recebem I/O quando nenhum outro programa está usando o disco - [systemd.timer(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd.timer.5.html) · systemd · RandomizedDelaySec atrasa aleatoriamente o horário das tarefas agendadas para espalhar a carga - [systemctl(1) — Linux manual page](https://man7.org/linux/man-pages/man1/systemctl.1.html) · systemd · list-timers: mostra as unidades de timer na ordem do próximo horário de execução - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -u mostra a CPU e -d o I/O de disco, por processo #### so-os-update · Mudança de desempenho após atualização de SO, kernel, driver ou firmware · Performance regression after OS / kernel / driver / firmware update É quando o código do jogo continua o mesmo, mas o servidor fica lento depois de uma atualização de SO, kernel, driver ou firmware. A atualização pode mudar valores padrão, o escalonador, as mitigações de vulnerabilidades da CPU (mitigations) e o comportamento de drivers. - Por quê → Efeito → Na tela: Um patch de segurança periódico ou uma nova imagem de servidor muda o kernel, drivers ou firmware → Valores padrão e escalonador mudam, ou novas mitigações de vulnerabilidades são ligadas: o mesmo trabalho gasta mais tempo de CPU e muda a ordem em que as threads recebem CPU → Um servidor que ia bem fica sempre um pouco mais lento desde o dia da atualização: input lag e, quando junta muita gente, engasgos e câmera lenta - Sintomas: Input lag, Engasgos, Câmera lenta / Fatores: Latência, Paralisação, Jitter - Quem: Servidor inteiro / Quando: Sempre, Quando junta muita gente - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Aplicar a atualização primeiro em alguns servidores e comparar tempo de tick, latência e uso de CPU com a versão anterior antes de ampliar, fazer o deploy em dia diferente do patch do jogo, registrar as versões de kernel, driver e firmware e os principais valores de sysctl antes e depois, se der problema dar boot no kernel anterior para confirmar, decidir sobre desligar as mitigações (mitigations=off) pesando o risco de segurança. - Números de referência: Quando a versão do kernel muda, o comportamento padrão também muda. Por exemplo, o Linux começou a migrar o escalonador do CFS para o EEVDF a partir da 6.6, e o padrão do teto da fila de conexões (somaxconn) mudou de 128 para 4.096 a partir da 5.4. As mitigações de vulnerabilidades da CPU acrescentam trabalho, como esvaziar buffers internos da CPU ao voltar do kernel para o programa (ao fim de cada chamada de sistema) e nas trocas de contexto e de máquina virtual, por isso servidores de rede que fazem chamadas de sistema a cada pacote sofrem mais. Algumas vulnerabilidades só são bloqueadas por completo desligando o SMT (o recurso que faz um núcleo funcionar como duas threads), e desligar o SMT pode derrubar muito o desempenho, dependendo da carga. O parâmetro de kernel mitigations=off desliga todas essas mitigações e recupera o desempenho, mas deixa o servidor exposto às vulnerabilidades. - No gráfico: Degrau a partir de um momento (Tempo de tick do servidor, uso de CPU, latência com a mesma carga) - Onde olhar: Cruzar o histórico de atualizações do gerenciador de pacotes, o horário do reboot, a versão do kernel (uname -r) e as informações do driver da NIC (ethtool -i) com o momento em que a latência subiu. Comparar com mpstat e pidstat servidores atualizados e não atualizados sob a mesma carga, e comparar também o estado das mitigações em /sys/devices/system/cpu/vulnerabilities/ - Confirma se: Latência e uso de CPU sobem um degrau a partir do reboot depois da atualização e ficam lá, e só os servidores atualizados ficam altos com a mesma carga. Dar boot no kernel ou driver anterior faz voltar ao normal - Descarta se: Servidores atualizados e não atualizados igualmente lentos com a mesma carga: não é esta causa. Houve deploy de patch do jogo no mesmo dia e o número ou o tamanho dos pacotes por jogador mudou: “Mudança no padrão de tráfego após um patch” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O estado das mitigações aparece nos arquivos em /sys/devices/system/cpu/vulnerabilities/. O padrão (mitigations=auto) aplica as mitigações com o SMT ligado, mas com auto,nosmt o SMT é desligado em CPUs vulneráveis, e o número de núcleos lógicos pode cair pela metade depois de atualizar o kernel. Atualizar o SO no mesmo dia de um patch do jogo dificulta descobrir a causa, então faça os deploys separados. - Fontes: - [The kernel’s command-line parameters](https://docs.kernel.org/admin-guide/kernel-parameters.html) · Linux kernel · mitigations=: off desliga todas as mitigações de vulnerabilidades da CPU e melhora o desempenho, mas deixa o sistema exposto; o padrão auto aplica as mitigações com o SMT ligado; auto,nosmt desliga o SMT quando necessário - [MDS - Microarchitectural Data Sampling](https://docs.kernel.org/admin-guide/hw-vuln/mds.html) · Linux kernel · As mitigações esvaziam buffers da CPU ao voltar do kernel para o espaço de usuário e ao entrar em uma máquina virtual; o estado das vulnerabilidades e das mitigações aparece nos arquivos em /sys/devices/system/cpu/vulnerabilities/; em muitas CPUs, o bloqueio completo exige desligar o SMT, o que pode afetar muito o desempenho, dependendo da carga - [Spectre Side Channels](https://docs.kernel.org/admin-guide/hw-vuln/spectre.html) · Linux kernel · Para mitigar, esvazia os buffers de predição de desvios nas trocas de contexto e de máquina virtual; as mitigações mais fortes acrescentam overhead a todos os programas - [EEVDF Scheduler](https://docs.kernel.org/scheduler/sched-eevdf.html) · Linux kernel · O Linux começou a migrar do CFS para o escalonador EEVDF a partir da 6.6 - [listen(2) — Linux manual page](https://man7.org/linux/man-pages/man2/listen.2.html) · Linux man-pages · O padrão do somaxconn mudou de 128 para 4.096 a partir do Linux 5.4 - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · ethtool -i consulta as informações do driver do dispositivo de rede #### so-conntrack · Tabela do conntrack cheia no servidor · conntrack table full Quando a tabela de rastreamento de conexões (conntrack), em que o firewall do Linux registra todas as conexões, chega ao limite, os pacotes novos são descartados. - Por quê → Efeito → Na tela: Pico de conexões e conexões curtas repetidas fazem crescer os registros de conexão → A tabela enche, e conexões novas e alguns pacotes são descartados → Não conecta, teleporte por perda sem causa aparente - Sintomas: Não conecta / loading infinito, Teleporte / Fatores: Perda de pacotes - Quem: Servidor inteiro / Quando: Logo após login ou manutenção, Quando junta muita gente - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: reduzir conexões curtas (reutilizar conexões nas chamadas entre servidores). Cliente: quando a conexão falhar ou cair, aumentar progressivamente o intervalo entre novas tentativas e espalhá-las aleatoriamente. - O que fazer (Equipe de infraestrutura): Aumentar o tamanho da tabela (nf_conntrack_max), tirar as portas do jogo do rastreamento (NOTRACK na tabela raw), alertar sobre o uso. - Números de referência: O limite padrão fica entre cerca de 60 mil e 260 mil entradas, conforme a memória do servidor. Quando transborda, o log do kernel mostra “nf_conntrack: table full, dropping packet”. - No gráfico: Achata ao bater no limite (Entradas do conntrack (nf_conntrack_count)) - Onde olhar: Pôr net.netfilter.nf_conntrack_count (entradas atuais) do sysctl no mesmo gráfico que nf_conntrack_max e procurar “nf_conntrack: table full, dropping packet” no dmesg - Confirma se: nf_conntrack_count achata no max, e a partir desse momento o log do kernel mostra table full - Descarta se: Entradas bem abaixo do max: não é esta causa. O limite de rastreamento de conexões da própria instância AWS aparece como conntrack_allowance_exceeded, em “Limite de PPS da nuvem excedido” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · O padrão de nf_conntrack_max é igual ao número de buckets do hash (nf_conntrack_buckets), que é definido pelo tamanho da memória - [net/netfilter/nf_conntrack_core.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_conntrack_core.c?h=v6.12) · Linux kernel · Tamanho padrão de 65.536 com mais de 1 GB de memória e de 262.144 com mais de 4 GB (64 bits); quando enche, registra “nf_conntrack: table full, dropping packet” e descarta - [iptables-extensions(8) — Linux manual page](https://man7.org/linux/man-pages/man8/iptables-extensions.8.html) · netfilter · Tirar do rastreamento de conexões com CT --notrack na tabela raw #### so-ports · Esgotamento de portas efêmeras em conexões entre servidores · Ephemeral port exhaustion (TIME_WAIT) Quando o servidor do jogo abre e fecha conexões curtas com frequência para o BD ou outros servidores, as conexões encerradas seguram a porta por um tempo e não dá para abrir conexões novas. - Por quê → Efeito → Na tela: Abre e fecha uma conexão nova a cada pedido → O lado que fecha primeiro segura a porta por cerca de 60 s no Linux (TIME_WAIT), e as portas disponíveis acabam → Pedidos internos falham: salvamentos falham e recursos dão erro - Sintomas: Ação perdida / rollback, Não conecta / loading infinito / Fatores: Perda de pacotes - Quem: Servidor inteiro, Só um recurso específico / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Reutilizar conexões (pool de conexões), não abrir e fechar uma conexão nova a cada pedido. - O que fazer (Equipe de infraestrutura): Ampliar a faixa de portas (ip_local_port_range), avaliar a reutilização de TIME_WAIT em conexões de saída (tcp_tw_reuse no Linux), monitorar o número de TIME_WAIT. - Números de referência: A faixa de portas padrão do Linux (32768–60999) tem cerca de 28 mil portas. Mais de 470 conexões novas por segundo para o mesmo endereço de destino esgotam essa faixa. O Windows tem cerca de 16 mil portas por padrão (49152–65535) e um TIME_WAIT mais longo, então esgota mais rápido. - No gráfico: Achata ao bater no limite (Sockets em TIME_WAIT, falhas de conexão interna) - Onde olhar: Contar os sockets em TIME_WAIT por endereço de destino com ss -tan state time-wait e procurar falhas de connect (EADDRNOTAVAIL) no log do servidor do jogo - Confirma se: Os TIME_WAIT para o mesmo destino (BD etc.) achatam perto do tamanho da faixa de portas efêmeras (cerca de 28 mil por padrão), e o connect falha com EADDRNOTAVAIL - Descarta se: Poucos TIME_WAIT, mas só as conexões para serviços externos falham: “Limite de conexões e portas do gateway NAT na nuvem” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: No Linux, os 60 s do TIME_WAIT são um valor fixo no kernel. Reduzir o tcp_fin_timeout, de nome parecido, não encurta o TIME_WAIT. - Fontes: - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · ip_local_port_range com padrão 32768–60999; tcp_tw_reuse; tcp_fin_timeout é o tempo de permanência no estado FIN_WAIT_2 - [include/net/tcp.h (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · TCP_TIMEWAIT_LEN(60*HZ): os cerca de 60 s do TIME_WAIT são uma constante do kernel - [TCP/IP port exhaustion troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/tcp-ip-port-exhaustion-troubleshooting) · Microsoft · Portas dinâmicas do Windows com padrão 49152–65535; conexões fechadas seguram a porta em TIME_WAIT por 4 minutos por padrão - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · O filtro de estado state time-wait mostra só os sockets em TIME_WAIT - [connect(2) — Linux manual page](https://man7.org/linux/man-pages/man2/connect.2.html) · Linux man-pages · EADDRNOTAVAIL: não dá para abrir a conexão porque todas as portas da faixa efêmera estão em uso ### L8 Sockets e protocolos (14 causas) #### sk-hol · HOL blocking no TCP · Head-of-line blocking Para manter a ordem, o TCP não entrega ao jogo os pacotes que chegaram depois enquanto não receber de novo o pacote perdido. - Por quê → Efeito → Na tela: Um pacote se perde → Os pacotes seguintes chegam, mas ficam esperando no buffer de recepção → Para e depois libera tudo de uma vez: avanço rápido - Sintomas: Travamento, Avanço rápido / Fatores: Perda de pacotes, Paralisação - Quem: Só eu / Quando: Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: usar UDP para posições em tempo real, entrega confiável só para o que for indispensável, dividir em vários streams. Cliente: mudar o tratamento de rede para o mesmo modelo do servidor (UDP, canais separados). - Números de referência: Perder um pacote causa uma parada de pelo menos um tempo de ida e volta, e mais um pouco. Se a retransmissão também se perder, a parada vai de centenas de ms a alguns segundos. - No gráfico: Lacuna e depois tudo junto (Volume recebido por conexão, retransmissões) - Onde olhar: Ver, numa captura de pacotes do lado do servidor (tcpdump ou Wireshark), os pacotes retransmitidos na conexão daquele jogador e as lacunas antes e depois deles; para o servidor inteiro, ver o aumento de TcpRetransSegs no nstat -az - Confirma se: A parada começa com a retransmissão de um único pacote, e os dados acumulados são processados todos de uma vez logo depois que o pacote retransmitido chega (o volume recebido fica em 0 e depois vem tudo junto) - Descarta se: Jogo que se comunica por UDP: não se aplica. Parada sem retransmissão: verificar o tick do servidor (“Estouro do tick”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · O TCP é um serviço de fluxo de bytes confiável e em ordem - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Detecta a perda com 3 ACKs duplicados e faz fast retransmit; se não, espera o timer de retransmissão - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · Backoff que dobra o timer de retransmissão cada vez que ele expira - [net/ipv4/proc.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nomes dos contadores mostrados pelo nstat: RetransSegs (segmentos retransmitidos) do grupo Tcp #### sk-rto · RTO do TCP e backoff exponencial · RTO and exponential backoff Cada vez que uma retransmissão falha de novo, o tempo de espera dobra, e uma queda curta da conexão vira uma pausa longa. - Por quê → Efeito → Na tela: A conexão cai por um instante e as retransmissões também falham em sequência → A espera até a próxima tentativa dobra a cada vez: 0,3 → 0,6 → 1,2 → 2,4 s (com ping de 100 ms) → A conexão caiu por 1 s, mas o jogo fica travado por mais de 2 s. Se a queda for mais longa, acaba em desconexão - Sintomas: Travamento, Desconexão / Fatores: Perda de pacotes, Paralisação - Quem: Só eu / Quando: Aleatoriamente, de vez em quando, Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: responder aos heartbeats e, se não receber nenhum por um certo tempo, encerrar a conexão por conta própria (reduzir o prazo de desistência com TCP_USER_TIMEOUT), retomar a sessão com um token de sessão, usar UDP confiável. Cliente: enviar heartbeats em intervalos curtos e, se as respostas pararem, reconectar logo, sem esperar a retransmissão do TCP. - Números de referência: No Linux, o RTO (tempo de espera para retransmitir) tem mínimo de “ping + 200 ms” e começa em 1 s no estabelecimento da conexão. Com a configuração padrão (tcp_retries2=15), mesmo com as retransmissões falhando sem parar, a conexão só é abandonada depois de cerca de 15 minutos. - No gráfico: Lacuna e depois tudo junto (RTO e backoff por conexão, expirações do RTO) - Onde olhar: Ver na conexão parada, com ss -ti, o rto (espera para retransmitir, em ms) e o backoff (expirações seguidas); para o servidor inteiro, o aumento de TcpExtTCPTimeouts (expirações do timer de retransmissão) no nstat -az - Confirma se: A conexão parada tem backoff de 1 ou mais e rto na casa dos segundos, e TCPTimeouts sobe nesse momento - Descarta se: Retransmissões resolvidas por fast retransmit, sem expiração do RTO: a parada é curta. Nesse caso: “HOL blocking no TCP” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · RTO inicial de 1 s; o RTO dobra cada vez que o timer expira (backoff exponencial) - [net/ipv4/tcp_input.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_input.c?h=v6.12) · Linux kernel · No Linux, RTO = RTT suavizado + variação do RTT, e a variação tem piso de tcp_rto_min (200 ms), então o RTO é pelo menos RTT + 200 ms - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rto_min_us com padrão de 200 ms; RTO inicial de 1 s para pedidos de conexão; com tcp_retries2=15, pelo menos 924,6 s (cerca de 15 minutos) até desistir - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rto (timer de retransmissão, em ms) e backoff (número de backoffs exponenciais) do -i - [net/ipv4/proc.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nomes dos contadores mostrados pelo nstat: TCPTimeouts do grupo TcpExt - [net/ipv4/tcp_timer.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_timer.c?h=v6.12) · Linux kernel · Cada vez que o timer de retransmissão expira, incrementa TCPTimeouts, soma 1 ao backoff e dobra o RTO (até o máximo) #### sk-nagle · Algoritmo de Nagle + ACK atrasado · Nagle + delayed ACK (TCP_NODELAY off) O algoritmo de Nagle, que junta pacotes pequenos antes de enviar, e o ACK atrasado, que demora para mandar o ACK, se combinam, e cada mensagem escrita em partes atrasa 40–200 ms. - Por quê → Efeito → Na tela: Mensagens pequenas escritas em partes sem ligar o TCP_NODELAY → Quem envia espera o ACK, e quem recebe atrasa o ACK → Ping da conexão baixo, mas todas as ações demoram por igual: input lag - Sintomas: Input lag / Fatores: Latência - Quem: Servidor inteiro, Só eu / Quando: Sempre, Ao fazer ações específicas - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: ligar o TCP_NODELAY, juntar as mensagens de um tick e escrever tudo de uma vez, não contar com formas de desligar o ACK atrasado do lado de quem recebe (o TCP_QUICKACK do Linux dura pouco, e no Windows é preciso mudar o registro em cada PC), porque o jogo não tem controle garantido sobre elas. Cliente: ligar o TCP_NODELAY, juntar as mensagens de um frame e escrever tudo de uma vez. - Números de referência: No Linux, o ACK atrasado costuma ser de 40 ms (até 200 ms, conforme a situação). No Windows, versões antigas usavam 200 ms e as atuais usam 40 ms (o template padrão do Windows Server 2019 usa 40 ms). Como o ACK atrasado é definido pelo SO de quem recebe, se o servidor envia mensagens em partes com o Nagle ligado, o atraso pode ser de 40–200 ms, dependendo do PC que recebe. - No gráfico: Sempre alto desde o início (Tempo de resposta das ações (RTT no jogo)) - Onde olhar: Ver o intervalo entre pedido e resposta numa captura de pacotes do lado do servidor (tcpdump ou Wireshark) e conferir se o código do servidor e do cliente liga o TCP_NODELAY - Confirma se: Ping da conexão baixo, mas lacunas de cerca de 40 ms (200 ms em versões antigas do Windows) se repetem entre pacotes pequenos e terminam logo depois que chega o ACK do outro lado. Somem ao ligar o TCP_NODELAY - Descarta se: Intervalo de resposta parecido com o ping da conexão: não é esta causa. Servidor do jogo demorando para gerar a resposta: processamento no servidor (“Acúmulo na fila de mensagens”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · O Nagle segura dados pequenos enquanto houver dados sem ACK; deve ser possível desligá-lo por conexão; o ACK atrasado deve ser menor que 0,5 s; o problema da combinação dos dois - [include/net/tcp.h (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · ACK atrasado do Linux com mínimo TCP_DELACK_MIN (HZ/25 = 40 ms) e máximo TCP_DELACK_MAX (HZ/5 = 200 ms) - [TCP improvements in the Windows network stack (IETF 98 TCPM)](https://datatracker.ietf.org/meeting/98/materials/slides-98-tcpm-tcp-improvements-in-windows-01) · Microsoft · O timeout padrão do ACK atrasado no Windows passou a ser 40 ms (apresentado em 2017) - [TCP Templates for Windows Server 2019 – How to tune your Windows Server Transports (Advanced users only 😉)](https://techcommunity.microsoft.com/blog/networkingblog/tcp-templates-for-windows-server-2019-8211-how-to-tune-your-windows-server-trans/339795) · Microsoft · Template do Server 2019: DelayedAckTimeout 40 ms, MaxSynRetransmissions 2, InitialRto 3000 ms - [Design issues - Sending small data segments over TCP with Winsock](https://learn.microsoft.com/en-us/previous-versions/troubleshoot/windows/win32/data-segment-tcp-winsock) · Microsoft · No TCP antigo do Windows, ao receber dados, arma-se um timer de ACK atrasado de 200 ms, e o Nagle vem ligado por padrão, então pacotes pequenos esperam o ACK; a solução é o TCP_NODELAY #### sk-block-send · Envio bloqueante por causa de cliente lento · Blocking send on a full socket Quando o buffer de envio de um jogador com conexão lenta enche e o servidor envia no modo bloqueante (em que a chamada só retorna quando abre espaço no buffer), a thread do servidor fica esperando esse único jogador. - Por quê → Efeito → Na tela: O buffer de envio de um cliente lento enche → Como o envio é bloqueante, a thread do servidor espera até abrir espaço no buffer → Travamento e câmera lenta para todos os jogadores daquela thread - Sintomas: Travamento, Câmera lenta / Fatores: Paralisação - Quem: Local ou canal específico, Servidor inteiro / Quando: Aleatoriamente, de vez em quando, Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Usar envio não bloqueante, limitar a fila de envio por cliente, descartar atualizações velhas. - No gráfico: Picos aleatórios (Tempo de tick do servidor, Send-Q por conexão) - Onde olhar: Procurar com ss -tn as conexões com Send-Q (bytes sem ACK ou ainda não enviados) cheio até o tamanho do buffer de envio, e ver no thread dump (pilhas) do servidor do jogo, no momento do pico de tick, se há threads paradas numa chamada send - Confirma se: Quando há uma conexão lenta com Send-Q cheio, a thread responsável por ela está parada no send, e só os jogadores dessa mesma thread travam juntos - Descarta se: Thread parada esperando fora do send (lock, chamada ao BD): “Contenção de lock”, “Chamadas síncronas na thread do jogo” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [send(2) — Linux manual page](https://man7.org/linux/man-pages/man2/send.2.html) · Linux man-pages · Sem espaço no buffer de envio, send() bloqueia; no modo não bloqueante, retorna na hora com EAGAIN - [send function (winsock2.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-send) · Microsoft · No Winsock, send também bloqueia quando falta espaço no buffer, a menos que o socket esteja em modo não bloqueante - [net/ipv4/tcp_diag.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Valores Recv-Q e Send-Q do ss: no socket em escuta, as conexões esperando o accept e o limite do backlog; no socket conectado, os bytes que o app ainda não leu e os bytes enviados ainda sem ACK #### sk-slow-client · Política para clientes lentos (slow consumer) · Slow-consumer policy Para um cliente cujos dados a enviar não param de acumular, o servidor descarta as atualizações antigas ou derruba a conexão. - Por quê → Efeito → Na tela: A conexão do cliente não acompanha o volume que o servidor envia → O servidor descarta atualizações antigas ou, ao passar do limite, encerra a conexão → Só esse jogador tem teleporte ou desconexão - Sintomas: Teleporte, Desconexão / Fatores: Perda de pacotes - Quem: Só eu / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Reduzir o volume enviado (frequência de atualização conforme a distância), continuar enviando com qualidade menor, reduzir o que fica acumulado no kernel (TCP_NOTSENT_LOWAT no Linux). - Números de referência: Com um buffer de envio de 256 KB, uma conexão de 30 KB/s acumula mais de 8 segundos de dados atrasados. O Linux pode aumentar esse buffer sozinho até vários MB. - No gráfico: Alto só em alguns (Send-Q por conexão, atualizações descartadas por cliente) - Onde olhar: Ver o que o servidor do jogo registra por cliente (tamanho da fila de envio, atualizações descartadas, motivo da desconexão) e conferir no servidor, com ss -tni, o Send-Q e o cwnd daquela conexão - Confirma se: Só as conexões dos jogadores que tiveram teleporte ou caíram ficam com Send-Q sempre cheio, e o log do jogo registra descarte de atualizações desses jogadores ou desconexão por estouro da fila de envio - Descarta se: Send-Q vazio, mas com teleporte: o problema não está no envio do servidor. Mais provável: perda na conexão desse jogador (“Perda no trecho sem fio”) ou interpolação na tela - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_wmem: máximo do buffer de envio ajustado automaticamente, com padrão de 64 KB–4 MB (conforme a memória); tcp_notsent_lowat e TCP_NOTSENT_LOWAT limitam a quantidade de dados ainda não enviados - [net/ipv4/tcp_diag.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Valores Recv-Q e Send-Q do ss: no socket em escuta, as conexões esperando o accept e o limite do backlog; no socket conectado, os bytes que o app ainda não leu e os bytes enviados ainda sem ACK #### sk-keepalive · Keepalive com valor padrão de 2 horas · TCP keepalive defaults Quando o outro lado some sem sinal de encerramento, o TCP só percebe muito depois. O keepalive (recurso do TCP que verifica se uma conexão ociosa continua viva) vem desligado por padrão e, mesmo ligado, só começa a verificar depois de 2 horas de inatividade. - Por quê → Efeito → Na tela: O cliente some sem sinal de encerramento porque o aparelho desligou ou a conexão caiu → O servidor considera a conexão viva (keepalive com padrão de 7.200 s; se havia dados sendo enviados, cerca de 15 minutos até desistir das retransmissões) → Fica um personagem fantasma e, ao reconectar, aparece o erro “já conectado” - Sintomas: Não conecta / loading infinito, Invisível / entidade fantasma / Fatores: Perda de pacotes - Quem: Só eu / Quando: Depois de ficar parado, Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Servidor: responder aos heartbeats e, se não receber nenhum por um certo tempo, encerrar a conexão por conta própria (ajustar TCP_KEEPIDLE e TCP_USER_TIMEOUT), na reconexão substituir a sessão antiga usando o token de sessão e retomá-la. Cliente: enviar heartbeats no nível do jogo a cada intervalo de alguns segundos a algumas dezenas de segundos (no máximo metade do menor timeout de inatividade), reconectar automaticamente quando cair. - O que fazer (Equipe de infraestrutura): Baixar os padrões do kernel (tcp_keepalive_time etc.) para os sockets em que o código não define valores próprios (vale só para sockets com SO_KEEPALIVE ligado). - Números de referência: No Linux, o padrão é começar a verificar após 7.200 s de inatividade, enviar 9 probes a cada 75 s e derrubar a conexão se não houver resposta até o fim. Somando, são cerca de 2 horas e 11 minutos. O Windows também só começa a verificar, por padrão, após 2 horas de inatividade. - No gráfico: Alto só em alguns (Tempo desde o último recebimento, por conexão) - Onde olhar: Ver com ss -tnoi o lastrcv (ms desde o último recebimento) e o timer de keepalive (timer:(keepalive,…)) de cada conexão e cruzar com os registros de recusa “já conectado” do servidor do jogo - Confirma se: Há conexões ESTABLISHED com lastrcv de alguns minutos a algumas horas, e a reconexão daquela conta é recusada com “já conectado” - Descarta se: Nenhuma conexão silenciosa há muito tempo, mas aparece “já conectado”: aponta para o código de limpeza de sessões do servidor do jogo - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · Após 7.200 s de inatividade, 9 probes a cada 75 s (cerca de 11 minutos a mais); vale só para sockets com SO_KEEPALIVE ligado; TCP_KEEPIDLE e TCP_USER_TIMEOUT - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · O keepalive deve vir desligado por padrão, e o intervalo de inatividade padrão deve ser de pelo menos 2 horas - [SO_KEEPALIVE socket option](https://learn.microsoft.com/en-us/windows/win32/winsock/so-keepalive) · Microsoft · Timeout padrão do keepalive TCP no Windows de 2 horas - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · lastrcv do -i (ms desde o último recebimento), timer:(keepalive,…) do -o #### sk-fragment · Fragmentação IP de pacotes UDP · IP fragmentation of large UDP Um pacote UDP maior que o MTU (o tamanho máximo que dá para enviar de uma vez) é fragmentado na camada IP, e perder um só fragmento faz o pacote inteiro ser descartado. - Por quê → Efeito → Na tela: Em lugares lotados, o snapshot passa de 1.500 bytes → Vai dividido em vários fragmentos, e perder qualquer um descarta o pacote inteiro → Pacotes grandes têm taxa de perda várias vezes maior. Teleporte só nos lugares lotados - Sintomas: Teleporte / Fatores: Perda de pacotes - Quem: Local ou canal específico, Região ou operadora específica / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Dividir os pacotes no próprio jogo em até 1.200 bytes, enviar só as mudanças. - Números de referência: Numa conexão com 2% de perda, um pacote dividido em 4 fragmentos se perde cerca de 8% das vezes. Alguns firewalls e operadoras descartam todos os pacotes fragmentados, e esses jogadores não recebem nenhum pacote grande. - No gráfico: Sobe com a carga (Fragmentações IP (IpFragCreates), tamanho do snapshot) - Onde olhar: Ver no servidor o aumento de IpFragCreates (fragmentos criados no envio) no nstat -az e, no lado que recebe, IpReasmFails (falhas de remontagem). Conferir a distribuição de tamanho dos pacotes UDP nos logs do servidor do jogo ou numa captura de pacotes - Confirma se: IpFragCreates sobe nos lugares lotados, há pacotes UDP acima de 1.500 bytes, e os reports de teleporte aumentam nesse momento - Descarta se: IpFragCreates não sobe: não há fragmentação no envio do servidor - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · Perder um fragmento impede a remontagem e o pacote inteiro se perde; apps UDP devem evitar a fragmentação IP - [RFC 8900: IP Fragmentation Considered Fragile](https://www.rfc-editor.org/rfc/rfc8900) · IETF · Casos de firewalls e de algumas redes que descartam fragmentos IP - [net/ipv4/proc.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nomes dos contadores mostrados pelo nstat: FragCreates (fragmentos criados) e ReasmFails (falhas de remontagem) do grupo Ip #### sk-reliable-udp · Configuração de retransmissão do UDP confiável · Reliable-UDP tuning (KCP, ENet…) Se as regras de retransmissão implementadas sobre o UDP forem conservadoras demais, a recuperação demora. Se forem agressivas demais, congestionam ainda mais a conexão. - Por quê → Efeito → Na tela: Intervalo, número de retransmissões e tamanho da janela não combinam com a conexão → Recuperação lenta, ou envios duplicados que pioram o congestionamento → Skill não sai, avanço rápido, lag pior quando há congestionamento - Sintomas: Ação perdida / rollback, Avanço rápido / Fatores: Perda de pacotes, Latência - Quem: Só eu / Quando: Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: retransmitir com base no tempo de ida e volta medido, separar canais por importância. Cliente: aplicar as mesmas configurações de retransmissão e de canais do servidor. - No gráfico: Picos aleatórios (Taxa de retransmissão do UDP confiável, RTT no jogo) - Onde olhar: Registrar no servidor e no cliente as estatísticas que a biblioteca usada mantém por conexão (retransmissões, tempo de ida e volta estimado, tempo de espera para retransmitir) e comparar com a taxa real de perda da conexão do mesmo jogador (medida com mtr) - Confirma se: Taxa de retransmissão várias vezes maior que a perda real da conexão: configuração agressiva demais. Espera para retransmitir várias vezes maior que o tempo de ida e volta medido: configuração conservadora demais - Descarta se: Taxa de retransmissão parecida com a perda da conexão e espera compatível com o tempo de ida e volta: não é problema de configuração. Verificar a perda na própria conexão - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · A retransmissão pode agravar o congestionamento e deve passar pelo controle de congestionamento; o tempo de ida e volta é estimado pela média de várias medições (EWMA), com valor inicial de 1 s; reduzir a taxa de envio quando o timer expira #### sk-slowstart · Slow start após inatividade · Slow start after idle Depois de um tempo ocioso, o TCP volta a reduzir a janela de congestionamento (quanto dá para enviar de uma vez) e, quando de repente precisa enviar muitos dados, divide o envio em várias rodadas. - Por quê → Efeito → Na tela: Uma conexão que estava ociosa envia muitos dados de uma vez, como ao entrar numa cidade → Com a janela de congestionamento reduzida, o envio é dividido em várias idas e voltas → Logo após a entrada, personagens e NPCs ao redor aparecem com atraso de algumas idas e voltas (mais visível em servidores distantes) - Sintomas: Input lag, Invisível / entidade fantasma / Fatores: Latência - Quem: Só eu / Quando: Em movimento ou ao trocar de mapa, Depois de ficar parado - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Reduzir os dados de entrada (enviar primeiro o que for indispensável). - O que fazer (Equipe de infraestrutura): Desligar o tcp_slow_start_after_idle (Linux, configuração do servidor inteiro). - Números de referência: Depois de ficar ocioso por mais tempo que o RTO, a janela de congestionamento começa a encolher e, após um longo período ocioso, cai para cerca de 14 KB (10 pacotes). Aí 100 KB não saem de uma vez e são enviados em 3 idas e voltas. - No gráfico: Alto só em alguns (Tempo de envio logo após a entrada (jogadores com RTT alto)) - Onde olhar: Conferir o valor de sysctl net.ipv4.tcp_slow_start_after_idle e ver no ss -ti, no momento em que o jogador entra numa área depois de ficar ocioso, se o cwnd (janela de congestionamento) daquela conexão diminuiu - Confirma se: A configuração está em 1 (padrão) e, no momento da entrada após inatividade, o cwnd cai para cerca de 10 e o envio se divide em várias idas e voltas. Quanto maior o RTT do jogador, maior o atraso para os personagens aparecerem, e o problema some ao mudar para 0 - Descarta se: cwnd continua grande, mas os personagens aparecem com atraso: processamento de entrada no servidor (“Avalanche de spawns ao entrar em área lotada”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_slow_start_after_idle vem ligado por padrão; se a conexão ficar ociosa por um RTO, a janela de congestionamento é reduzida (método do RFC 2861) - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Se nenhum dado foi enviado por mais tempo que o RTO, a janela de congestionamento cai para no máximo a janela de reinício min(IW, cwnd) e volta o slow start - [RFC 6928: Increasing TCP's Initial Window](https://www.rfc-editor.org/rfc/rfc6928) · IETF · Janela inicial de 10 segmentos, até 14.600 bytes - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · cwnd (janela de congestionamento) e ssthresh (limiar do slow start) do -i #### sk-congestion · Queda brusca da taxa de envio pelo controle de congestionamento · Congestion control backoff O TCP trata a perda como sinal de congestionamento e reduz a taxa de envio em 30–50%. Ele reage do mesmo jeito à perda no Wi-Fi. - Por quê → Efeito → Na tela: Com muito a enviar, ocorre um pouco de perda no Wi-Fi ou na conexão → O TCP reduz muito a taxa de envio e se recupera devagar (o CUBIC, padrão no Linux e no Windows, reduz 30%) → Em lugares lotados, as atualizações atrasam: avanço rápido e input lag - Sintomas: Avanço rápido, Input lag / Fatores: Latência, Paralisação - Quem: Só eu / Quando: Quando junta muita gente - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Reduzir o volume enviado (área de interesse, só as mudanças), dividir o envio para não mandar tudo de uma vez. - O que fazer (Equipe de infraestrutura): Trocar para um controle de congestionamento como o BBR (tcp_congestion_control). - No gráfico: Dente de serra (Janela de congestionamento (cwnd) e taxa de envio por conexão) - Onde olhar: Capturar várias vezes, com ss -ti, a conexão do jogador com atualizações atrasadas e ver a variação de cwnd e ssthresh e o nome do controle de congestionamento (cubic ou bbr), observando também se o Send-Q acumula - Confirma se: Depois de uma perda, o cwnd cai muito e sobe devagar, repetidamente, e enquanto está baixo o Send-Q acumula, coincidindo com o horário dos reports de avanço rápido e input lag - Descarta se: cwnd com folga, mas os dados atrasam: janela de quem recebe (“Janela zero (paralisação que parece retransmissão)”) ou envio no servidor - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 9438: CUBIC for Fast and Long-Distance Networks](https://www.rfc-editor.org/rfc/rfc9438) · IETF · Na perda, o CUBIC multiplica a janela por 0,7 (redução de 30%) e o Reno, por 0,5; o CUBIC é o padrão no Linux, no Windows e nos sistemas da Apple - [TCP BBR congestion control comes to GCP – your Internet just got faster](https://cloud.google.com/blog/products/networking/tcp-bbr-congestion-control-comes-to-gcp-your-internet-just-got-faster) · Google Cloud · O controle de congestionamento baseado em perda reduz muito a taxa de envio mesmo em perdas que não vêm de congestionamento; o BBR decide pela taxa de entrega e pelo RTT - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_congestion_control escolhe o algoritmo de controle de congestionamento das conexões novas - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · cwnd, ssthresh e nome do algoritmo de controle de congestionamento no -i - [net/ipv4/tcp_diag.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Valores Recv-Q e Send-Q do ss: no socket em escuta, as conexões esperando o accept e o limite do backlog; no socket conectado, os bytes que o app ainda não leu e os bytes enviados ainda sem ACK #### sk-linger · Perda dos últimos dados no encerramento forçado por RST · SO_LINGER, abrupt RST Quando o servidor fecha a conexão às pressas, o último aviso enviado ou o sinal de salvamento concluído se perde. - Por quê → Efeito → Na tela: O servidor fecha a conexão com encerramento forçado (RST). Acontece com SO_LINGER em 0 s ou ao fechar sem ler todos os dados recebidos → O motivo do kick e os últimos dados que ainda estavam sendo enviados são descartados → “Conexão encerrada por erro desconhecido” sem motivo aparente - Sintomas: Desconexão / Fatores: Perda de pacotes - Quem: Só eu / Quando: Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Depois de enviar o motivo, fechar primeiro só a direção de envio (shutdown), ler até o fim os dados recebidos até o outro lado fechar e só então fechar, evitar SO_LINGER com 0 s. - No gráfico: Picos aleatórios (Conexões encerradas com RST) - Onde olhar: Ver o aumento de TcpExtTCPAbortOnData (fechou com RST com dados ainda por enviar, SO_LINGER em 0 s) e TcpExtTCPAbortOnClose (fechou com dados não lidos) no nstat -az, e ver numa captura de pacotes do lado do servidor, no momento da queda, se o servidor fecha com RST ou com FIN - Confirma se: No horário dos reports de “Conexão encerrada por erro desconhecido”, o servidor envia RST, e AbortOnData e AbortOnClose sobem - Descarta se: O servidor encerrou normalmente com FIN, mas o motivo não aparece: aponta para o tratamento do encerramento no cliente - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [closesocket function (winsock.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-closesocket) · Microsoft · Com SO_LINGER ligado e tempo 0, o fechamento vira um encerramento forçado que reseta a conexão na hora, e os dados não enviados se perdem - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · Fechar com dados recebidos ainda não lidos envia RST para avisar da perda de dados - [Graceful Shutdown, Linger Options, and Socket Closure](https://learn.microsoft.com/en-us/windows/win32/winsock/graceful-shutdown-linger-options-and-socket-closure-2) · Microsoft · Sequência: fechar primeiro só o envio com shutdown e fechar o socket depois de receber o aviso de encerramento do outro lado - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPAbortOnData: fechou com RST com dados ainda por enviar, por exemplo com SO_LINGER em 0 s; TcpExtTCPAbortOnClose: fechou com dados não lidos e enviou RST #### sk-blocking-io · Arquitetura de I/O bloqueante · Blocking I/O model Numa arquitetura em que a thread não pode fazer mais nada enquanto espera um socket, tudo fica mais lento à medida que entram mais jogadores. - Por quê → Efeito → Na tela: Cada conexão espera a leitura e a escrita → O atraso de uma conexão se espalha para as outras conexões da mesma thread → Quanto mais jogadores simultâneos, mais tudo fica em câmera lenta e com input lag - Sintomas: Câmera lenta, Input lag / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Quando junta muita gente, Horário de pico à noite - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Migrar para I/O assíncrono baseado em epoll, IOCP ou io_uring. - No gráfico: Sobe com a carga (Tempo de resposta, número de threads) - Onde olhar: Ver com pidstat -w -t o número de threads do servidor do jogo e as trocas de contexto voluntárias por thread (cswch/s, quantas vezes parou esperando um recurso), e comparar com o tempo de resposta conforme o número de jogadores simultâneos - Confirma se: Com mais jogadores simultâneos, o tempo de resposta sobe de forma íngreme, e a maioria das threads (que cresceram junto com o número de conexões) só tem trocas voluntárias e quase não usa CPU (esperando o socket) - Descarta se: Threads usando CPU sem parar, sem esperar: sobrecarga de cálculo (“Estouro do tick”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [epoll(7) — Linux manual page](https://man7.org/linux/man-pages/man7/epoll.7.html) · Linux man-pages · Notificação de eventos de I/O que escala para vigiar muitos fds de uma vez - [I/O Completion Ports](https://learn.microsoft.com/en-us/windows/win32/fileio/i-o-completion-ports) · Microsoft · Modelo do Windows que processa muito I/O assíncrono com um pool de threads criado de antemão - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · cswch/s do -w: trocas de contexto voluntárias, quando a thread para sozinha esperando um recurso; -t mostra por thread #### sk-reuseport · Distribuição desbalanceada do SO_REUSEPORT · SO_REUSEPORT imbalance, stuck worker Quando vários processos dividem a mesma porta, o kernel escolhe o processo responsável por cada conexão pelo hash do endereço e não muda mais. Se um desses processos para, só os jogadores atribuídos a ele ficam esperando. - Por quê → Efeito → Na tela: O gateway ou o servidor de login sobe vários processos com SO_REUSEPORT → Mesmo que um processo pare por GC ou sobrecarga, as conexões novas e os pacotes UDP atribuídos a ele não passam para outro processo → Só alguns jogadores não conectam ou têm travamento. Em reinícios que mudam o número de processos, algumas sessões UDP caem - Sintomas: Não conecta / loading infinito, Travamento, Desconexão / Fatores: Paralisação, Perda de pacotes - Quem: Só eu, Servidor inteiro / Quando: Logo após login ou manutenção, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Nunca deixar a thread de recepção parar, implementar um procedimento de transferência de sessão no reinício. - O que fazer (Equipe de infraestrutura): Monitorar a fila de conexões por processo (Recv-Q no ss), seguir o procedimento de transferência de sessão quando um deploy mudar o número de processos. - No gráfico: Alto só em alguns (Fila de conexões por socket em escuta (Recv-Q)) - Onde olhar: Ver com ss -ltnp o Recv-Q (conexões esperando o accept) e o processo responsável de cada socket em escuta na mesma porta, e comparar a vazão por processo - Confirma se: Entre os vários sockets da mesma porta, só um acumula Recv-Q sem parar, e o processo dele está parado ou com vazão perto de 0 - Descarta se: Recv-Q acumulando por igual em todos os sockets: sobrecarga geral (“Estouro da fila de conexões (backlog)”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [socket(7) — Linux manual page](https://man7.org/linux/man-pages/man7/socket.7.html) · Linux man-pages · Com SO_REUSEPORT, vários sockets fazem bind no mesmo endereço e dividem as conexões TCP e os pacotes UDP - [net/core/sock_reuseport.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/core/sock_reuseport.c?h=v6.12) · Linux kernel · Sem programa BPF, escolhe o socket responsável dividindo o hash do pacote pelo número de sockets do grupo - [Why does one NGINX worker take all the load?](https://blog.cloudflare.com/the-sad-state-of-linux-socket-balancing/) · Cloudflare · O SO_REUSEPORT divide as filas por worker com um hash simples, então, se um worker fica bloqueado, todas as conexões acumuladas na fila dele ficam paradas - [net/ipv4/tcp_diag.c (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Valores Recv-Q e Send-Q do ss: no socket em escuta, as conexões esperando o accept e o limite do backlog; no socket conectado, os bytes que o app ainda não leu e os bytes enviados ainda sem ACK #### sk-udp-connreset · Erro WSAECONNRESET em socket UDP no Windows · WSAECONNRESET on a Windows UDP socket Quando um servidor Windows envia UDP para um cliente que já saiu, volta um aviso de “porta inexistente” (ICMP). Esse aviso faz a próxima chamada de recepção terminar com erro, e, se o código do servidor tratar esse erro como falha do próprio socket, todos que usam aquele socket são afetados. - Por quê → Efeito → Na tela: O servidor continua enviando UDP para o endereço de um cliente que acabou de sair, e volta o aviso de “porta inexistente” (ICMP) → O Windows encerra a chamada de recepção seguinte com o erro WSAECONNRESET (10054), e o código do servidor para de receber ou fecha o socket → Todos que usavam aquele socket têm travamento ou desconexão ao mesmo tempo - Sintomas: Desconexão, Travamento / Fatores: Perda de pacotes, Paralisação - Quem: Servidor inteiro / Quando: Aleatoriamente, de vez em quando, Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Desligar o SIO_UDP_CONNRESET com WSAIoctl para não receber esse aviso, em caso de erro de recepção só registrar no log e continuar recebendo. - No gráfico: Queda de conexões em massa (Conexões, logs de erro de recepção) - Onde olhar: Procurar no log do servidor do jogo o código de erro de recepção UDP (WSAECONNRESET, 10054) e registros de parada do loop de recepção ou de fechamento do socket, e ver numa captura de pacotes do lado do servidor se chegou um ICMP Port Unreachable logo antes - Confirma se: Logo antes da desconexão em massa há um erro de recepção WSAECONNRESET registrado e, antes dele, chegou um ICMP Port Unreachable do endereço de um cliente que acabara de sair - Descarta se: Servidor Linux, ou código que já desliga o SIO_UDP_CONNRESET: não se aplica - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Winsock IOCTLs](https://learn.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls) · Microsoft · SIO_UDP_CONNRESET liga e desliga a notificação de “porta inexistente” (PORT_UNREACHABLE) no UDP - [recvfrom function (winsock.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recvfrom) · Microsoft · Num socket UDP, WSAECONNRESET significa que um envio anterior recebeu ICMP Port Unreachable - [Windows Sockets Error Codes](https://learn.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2) · Microsoft · Código de erro WSAECONNRESET: 10054 ### L9 Processo do jogo no servidor (18 causas) #### sp-tick-overrun · Estouro do tick · Tick overrun Quando o trabalho de um tick passa do orçamento, o intervalo entre ticks do servidor se alonga, e a área inteira fica lenta ou com engasgos. - Por quê → Efeito → Na tela: O trabalho de um tick (ex.: 50 ms) passa do orçamento → O estado do jogo, que deveria ser calculado 20 vezes por segundo, é calculado só 8 → Câmera lenta na área inteira (ou engasgos, conforme o design do servidor), skills demorando a responder - Sintomas: Câmera lenta, Input lag, Engasgos / Fatores: Paralisação - Quem: Local ou canal específico, Servidor inteiro / Quando: Quando junta muita gente, Horário de pico à noite - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Reduzir os cálculos pesados, dividir o tick entre várias threads, distribuir os jogadores entre canais, registrar o tempo de tick como métrica. - O que fazer (Equipe de infraestrutura): Incluir o tempo de tick e o uso de CPU por núcleo no monitoramento e nos alertas, avaliar CPUs ou instâncias com bom desempenho por núcleo (clock alto). - Números de referência: O orçamento é de 50 ms num servidor de 20 ticks, 33 ms com 30 ticks e 16,7 ms com 60 ticks. Para aguentar picos repentinos, é mais seguro deixar folga e usar normalmente só cerca de metade do orçamento. - No gráfico: Sobe com a carga (Tempo de tick do servidor, jogadores por zona ou canal, CPU da thread do jogo) - Onde olhar: Tempo de processamento do tick (p99) e número de estouros registrados pelo servidor, no mesmo gráfico do número de jogadores por zona ou canal. Sem métrica de tick, uso de CPU da thread do jogo com pidstat -t 1 - Confirma se: Quando lota, o tempo de tick passa do orçamento (50 ms a 20 ticks), e enquanto isso a thread do jogo fica perto de 100% de CPU - Descarta se: Ticks estouram com pouca CPU na thread do jogo: aponta para espera (pausa do GC, locks, chamadas síncronas). Latência alta na fila de execução no bcc runqlat: a thread não está recebendo tempo de CPU, então aponta para falta de CPU ou excesso de threads - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Como o tick atrasado aparece depende do design do servidor. Num servidor que avança o estado do jogo um tempo fixo por tick (ex.: 50 ms), o próprio tempo do jogo fica mais lento e tudo entra em câmera lenta. Num servidor que avança de uma vez o tempo que realmente passou, a velocidade do jogo se mantém, mas os pacotes ficam espaçados e os movimentos ficam grandes, o que aparece como engasgos e teleporte. Nos dois casos, a resposta aos comandos atrasa. Se uma única thread do jogo cuida do servidor inteiro, o servidor inteiro fica lento; se há uma thread por área, só aquela área. Alguns jogos, como o EVE Online, desaceleram de propósito o tempo do jogo em até 10 vezes nas batalhas grandes (Time Dilation) para o cálculo conseguir acompanhar. - Casos reais: eve-hedgp-2014 - Fontes: - [VALORANT's 128-Tick Servers](https://www.riotgames.com/en/news/valorants-128-tick-servers) · Riot Games · Um servidor de 128 ticks precisa terminar cada frame em 7,8125 ms; o tempo de frame do servidor é medido por subsistema e o orçamento é dividido entre eles - [HED-GP Technical Retrospective: What a HED-ache](https://www.eveonline.com/news/view/what-a-hed-ache) · CCP Games · Sob sobrecarga, o EVE Online desacelera o tempo do jogo com o Time Dilation, com piso de 10% (10 vezes mais lento); normalmente a CPU dos nós fica abaixo de 80% - [Handling variation in time](https://docs.unity3d.com/Manual/time-handling-variations.html) · Unity · Quando a simulação de passo fixo atrasa, os passos de recuperação rodam em sequência, e o tempo acima do limite é descartado, então o tempo do jogo corre mais devagar que o real - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -t mostra também as estatísticas por thread do processo (uso de CPU etc.) - [Demonstrations of runqlat, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/runqlat_example.txt) · IO Visor · Mostra em histograma a latência da fila de execução do escalonador (quanto tempo uma tarefa esperou para receber CPU) #### sp-aoi · Explosão N² no cálculo de visibilidade (AOI) · Area-of-interest explosion Se o servidor compara todos com todos para saber quem pode ver quem, quando o número de jogadores aumenta 10 vezes, o cálculo aumenta 100 vezes. - Por quê → Efeito → Na tela: Compara a distância entre todos os personagens, ou, mesmo dividindo em grade (grid), centenas de jogadores se juntam perto de uma célula → Com 100 jogadores são cerca de 10 mil comparações; com 1.000, cerca de 1 milhão → Em aglomerações, como world boss e guerra de castelo, o tick dispara: câmera lenta e engasgos - Sintomas: Câmera lenta, Engasgos / Fatores: Paralisação - Quem: Local ou canal específico, Servidor inteiro / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Dividir em grade ou setores e comparar só com quem está perto, atualizar com menos frequência quem está longe, limitar o número de jogadores que cada um vê. - Números de referência: Somando a comparação de distância e a atualização das listas de quem vê e quem não vê, se cada par de jogadores custa 0,1 µs (um décimo de milionésimo de segundo), 1.000 jogadores (cerca de 1 milhão de pares) dão 100 ms por tick. É o dobro do orçamento de 20 ticks (50 ms). - No gráfico: Sobe com a carga (Tempo de tick do servidor, jogadores reunidos num só lugar) - Onde olhar: Jogadores por zona ou canal e tempo de tick no mesmo gráfico, com o tempo gasto no cálculo de visibilidade medido à parte dentro do tick. Sem essa medição, a fatia de CPU por função do processo do jogo com perf top -p - Confirma se: Quando o número de jogadores reunidos num lugar dobra, o tempo de tick quase quadruplica, e as funções de visibilidade e de distância ocupam a maior parte do tempo de CPU - Descarta se: Tempo de tick crescendo na proporção do número de jogadores, ou funções de envio e serialização com fatia grande: explosão de broadcast ou custo de serialização e compressão - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Comparing Interest Management Algorithms for Massively Multiplayer Games](https://www.sable.mcgill.ca/~clump/papers/boulanger-06-comparing.pdf) · ACM · Artigo do NetGames 2006 (versão publicada pelos autores). Medir a distância de todos os pares não aguenta o aumento de jogadores; com uma grade quadrada, basta verificar as 9 células em volta - [Replication Graph in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/replication-graph-in-unreal-engine) · Epic Games · O modelo padrão, que avalia todas as conexões para cada ator, vira gargalo de CPU no servidor com muitos jogadores e atores; MMORPGs e similares dividem o mundo em grade e reutilizam as listas por célula - [perf-top(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-top.1.html) · perf · Mostra em tempo real a fatia de uso de CPU por função (símbolo) de um processo (-p) ou thread (-t) em execução #### sp-broadcast · Explosão de broadcast · Broadcast fan-out (N×N) Se o movimento de cada jogador é enviado a todos que o veem, o número de atualizações a enviar cresce com o quadrado do número de jogadores reunidos. - Por quê → Efeito → Na tela: A mudança de um jogador é enviada a todos que podem vê-lo → Com 1.000 jogadores vendo uns aos outros, são 1 milhão de atualizações por tick → A fila de envio e a largura de banda saturam: atraso e perda (input lag, avanço rápido, teleporte) - Sintomas: Input lag, Teleporte, Avanço rápido / Fatores: Latência, Perda de pacotes - Quem: Local ou canal específico, Servidor inteiro / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Reduzir a frequência de atualização conforme a distância e a importância (inimigos próximos a cada tick, jogadores distantes algumas vezes por segundo), limitar o volume enviado a cada jogador e preencher primeiro o que é mais importante, juntar várias atualizações num pacote, limitar o número de jogadores exibidos. - O que fazer (Equipe de infraestrutura): Comparar a largura de banda de envio e os pacotes por segundo de cada servidor com os limites de rede da NIC e da instância e alertar, conferir a folga antes de eventos grandes. - Números de referência: 1.000 jogadores × 1.000 jogadores × 20 ticks = 20 milhões por segundo. A 40 bytes cada, são cerca de 6,4 Gbps no servidor inteiro e cerca de 6,4 Mbps por jogador que recebe. Limitando a 150 jogadores visíveis, cai para cerca de 1 Gbps no total e cerca de 1 Mbps por jogador. - No gráfico: Sobe com a carga (Pacotes e bytes enviados pelo servidor, jogadores reunidos num só lugar) - Onde olhar: txpck/s e txkB/s do sar -n DEV 1 (pacotes e KB enviados por segundo pela NIC do servidor) junto com o gráfico de jogadores. Em instâncias de nuvem, os contadores de limite excedido do ethtool -S (no ENA da AWS, bw_out_allowance_exceeded e pps_allowance_exceeded) - Confirma se: Quando o número de jogadores reunidos aumenta, os pacotes e bytes enviados crescem mais rápido que o número de jogadores (quase ao quadrado), e a partir do momento em que batem no limite os contadores de limite excedido ou os descartes no envio sobem - Descarta se: Volume enviado estável, mas o tempo de tick sobe: cálculo de visibilidade ou lógica do jogo - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Casos reais: eve-hedgp-2014 - Fontes: - [HED-GP Technical Retrospective: What a HED-ache](https://www.eveonline.com/news/view/what-a-hed-ache) · CCP Games · O envio O(n²), em que n jogadores precisam ver a ação de n jogadores, é o fator limitante inevitável das grandes batalhas de frotas - [Actor Priority in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-priority-in-unreal-engine) · Epic Games · Quando a largura de banda da conexão satura, cada ator recebe uma prioridade (distância, linha de visão, tempo desde o último envio) e a banda é distribuída a partir dos mais importantes - [Detailed Actor Replication Flow in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/detailed-actor-replication-flow-in-unreal-engine) · Epic Games · NetUpdateFrequency define a frequência de atualização de cada ator; o envio segue a ordem de prioridade e, quando a conexão satura, o restante fica para o próximo tick - [sar(1) — Linux manual page](https://man7.org/linux/man-pages/man1/sar.1.html) · sysstat · rxpck/s e txpck/s (pacotes recebidos e enviados por segundo) e rxkB/s e txkB/s (KB recebidos e enviados por segundo) do sar -n DEV - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · bw_out_allowance_exceeded (limite de largura de banda de envio excedido) e pps_allowance_exceeded (limite de PPS excedido): número de pacotes enfileirados ou descartados #### sp-hotzone · Sobrecarga de zona em thread única (hotspot) · Single-threaded hot zone Numa arquitetura em que cada área fica com uma thread, quando todo mundo se junta num lugar, só aquele núcleo vai a 100%. - Por quê → Efeito → Na tela: Uma única thread cuida de uma área (canal) → Quando todo mundo se junta num lugar, só aquele núcleo satura, e os outros ficam com folga → Só aquela área tem lag, as outras estão normais - Sintomas: Câmera lenta, Input lag / Fatores: Paralisação - Quem: Local ou canal específico / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Distribuir entre canais, paralelizar dentro da área, limitar o número de jogadores. - O que fazer (Equipe de infraestrutura): Incluir o uso de CPU por núcleo no monitoramento e nos alertas (na média do servidor inteiro, a saturação de um núcleo some). - Números de referência: Num servidor de 16 núcleos, mesmo com um núcleo em 100%, o uso total de CPU aparece como cerca de 6%. Só olhando o uso por núcleo dá para achar. - No gráfico: Sobe com a carga (Uso de CPU por núcleo, CPU por thread) - Onde olhar: Uso por núcleo com mpstat -P ALL 1 e CPU por thread do processo do jogo com pidstat -t 1, comparando com o número de jogadores da zona que a thread mais ocupada atende - Confirma se: A CPU total do servidor está baixa, mas uma única thread (um único núcleo) fica perto de 100%, e nesse momento a zona dessa thread está lotada - Descarta se: Vários núcleos altos por igual: sobrecarga do servidor inteiro. Só o %soft (processamento de recepção) de um núcleo alto: aponta para interrupções da NIC concentradas em um só núcleo - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: As outras áreas só ficam normais quando cada área roda o seu tick separadamente. Se as threads das várias áreas esperam umas pelas outras a cada tick para avançar juntas ao próximo, a área mais ocupada atrasa o tick do servidor inteiro. - Casos reais: eve-hedgp-2014 - Fontes: - [Time Dilation – How’s That Going?](https://www.eveonline.com/news/view/time-dilation-hows-that-going) · CCP Games · O Time Dilation do EVE Online age por nó, então até sistemas solares distantes que estão no mesmo nó ficam lentos; batalhas grandes rodam em nós reforçados com apenas 4 sistemas solares - [mpstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/mpstat.1.html) · sysstat · Mostra separadamente o uso por processador e a média geral (-P ALL); %soft é a proporção de tempo gasto tratando interrupções de software - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -t mostra também as estatísticas por thread do processo (uso de CPU etc.) #### sp-lock · Contenção de lock · Lock contention Quando várias threads esperam o mesmo lock para usar os mesmos dados, só uma roda por vez, por mais threads que se acrescentem. - Por quê → Efeito → Na tela: Várias threads usam ao mesmo tempo dados compartilhados, como a casa de leilões ou o baú da guilda → As outras esperam até a thread que pegou o lock terminar → Só um recurso específico fica lento; nos casos graves, o tick inteiro atrasa - Sintomas: Input lag, Travamento / Fatores: Paralisação - Quem: Só um recurso específico, Servidor inteiro / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Dividir os locks em partes menores, reduzir o trabalho feito dentro do lock, usar uma arquitetura baseada em mensagens (cada dado tem uma thread responsável, e as outras threads só enviam pedidos por mensagem). - Números de referência: Se o trabalho dentro do lock é 20% do total, por mais threads que se acrescentem, a vazão para em no máximo 5 vezes a de uma thread; com 40%, para em 2,5 vezes. - No gráfico: Sobe com a carga (Tempo de processamento dos pedidos, CPU e trocas de contexto por thread) - Onde olhar: Trocas de contexto voluntárias por thread (cswch/s, quantas vezes parou esperando um recurso) com pidstat -w -t 1, e onde a thread espera fora da CPU (tempo de espera por pilha de chamadas) com bcc offcputime -p. No .NET, o número de contenções de lock no dotnet-counters (dotnet.monitor.lock_contentions a partir do .NET 9, Monitor Lock Contention Count até o 8) - Confirma se: Mesmo com mais carga, o uso de CPU fica baixo, mas o tempo de processamento sobe, a maior parte do tempo de espera se concentra nas pilhas de chamadas que tentam pegar o lock, e o número de contenções de lock sobe junto - Descarta se: CPU no máximo: problema de volume de cálculo (estouro do tick, sobrecarga de zona em thread única). Espera em chamadas ao BD ou a arquivos: aponta para chamadas síncronas na thread do jogo - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Acontece em arquiteturas em que várias threads alteram juntas os dados do jogo. Arquiteturas em que cada área ou recurso fica com uma thread e a comunicação é só por mensagens quase não têm locks, mas é preciso cuidar do acúmulo de trabalho numa thread só (sobrecarga de zona em thread única). Se a thread do jogo espera um lock segurado por uma operação lenta de salvamento, o tick inteiro para. - Casos reais: roblox-2021 - Fontes: - [Amdahl's Law in the Multicore Era](https://research.cs.wisc.edu/multifacet/papers/ieeecomputer08_amdahl_multicore.pdf) · IEEE · Artigo da IEEE Computer de 2008 (versão publicada pelos autores). Se a fração que não dá para paralelizar é 1−f, o ganho de velocidade não passa de 1/(1−f), por mais núcleos que se acrescentem (lei de Amdahl) - [Request scheduling](https://learn.microsoft.com/en-us/dotnet/orleans/grains/request-scheduling) · Microsoft · Os grains (atores) do Orleans seguem um modelo de execução em thread única que processa um pedido de cada vez até o fim, então o estado nunca é alterado ao mesmo tempo; se esperarem as respostas uns dos outros, pode haver deadlock - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · cswch/s do -w é o número de trocas de contexto voluntárias, quando a thread para esperando um recurso; -t mostra por thread - [Demonstrations of offcputime, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/offcputime_example.txt) · IO Visor · Soma, por pilha de chamadas, o tempo em que as threads ficaram paradas fora da CPU (off-CPU); -p especifica o processo - [Well-known EventCounters in .NET](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/available-counters) · Microsoft · Monitor Lock Contention Count (monitor-lock-contention-count): número de vezes em que houve contenção ao tentar pegar um monitor lock - [.NET runtime metrics](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/built-in-metrics-runtime) · .NET · A partir do .NET 9, dotnet.monitor.lock_contentions: número de vezes, desde o início do processo, em que houve contenção ao tentar pegar um monitor lock #### sp-deadlock · Deadlock · Deadlock Quando duas threads esperam, cada uma, o lock que a outra segura, as duas ficam paradas para sempre. - Por quê → Efeito → Na tela: A thread A segura o lock 1 e espera o lock 2; a B segura o lock 2 e espera o lock 1 → As duas param para sempre, e as threads relacionadas vão parando em cadeia → O servidor inteiro para, e o watchdog o reinicia: desconexão de todos - Sintomas: Travamento, Desconexão / Fatores: Paralisação - Quem: Servidor inteiro, Só um recurso específico / Quando: Aleatoriamente, de vez em quando, Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Definir uma regra de ordem para os locks, usar locks com timeout, ter um watchdog e gravar um thread dump no momento da parada. - No gráfico: Queda de conexões em massa (Conexões, volume enviado pelo servidor) - Onde olhar: Capturar as pilhas de chamadas de todas as threads durante a parada. Na JVM, jstack (detecta e mostra deadlocks automaticamente); no .NET, dotnet-stack; em servidores nativos, thread apply all bt no gdb, ou gerar um core file com gcore, reiniciar e analisar depois - Confirma se: Duas ou mais threads estão paradas em pilhas que esperam o lock que a outra segura, e enquanto isso o uso de CPU do processo fica perto de 0 - Descarta se: Uma thread rodando a 100% de CPU durante a parada: loop infinito. Threads esperando resposta do BD ou de serviços externos: aponta para chamadas síncronas ou esgotamento do pool de threads - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Runtime locking correctness validator](https://docs.kernel.org/locking/lockdep-design.html) · Linux kernel · Pegar dois locks em ordem inversa causa espera circular e deadlock (lock inversion deadlock); o kernel Linux verifica a ordem dos locks e avisa antes - [Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/workloads/pods/probes/) · Kubernetes · A liveness probe detecta um deadlock (o processo roda, mas não avança) e reinicia o contêiner - [Diagnostic Tools (Java SE 21 Troubleshooting Guide)](https://docs.oracle.com/en/java/javase/21/troubleshoot/diagnostic-tools.html) · Oracle · jstack imprime as pilhas de todas as threads de uma JVM em execução e também detecta deadlocks (Found one Java-level deadlock) - [dotnet-stack diagnostic tool - .NET CLI](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-stack) · Microsoft · Captura e imprime as pilhas gerenciadas de todas as threads de um processo .NET - [Threads (Debugging with GDB)](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Threads.html) · GNU Project · thread apply all executa o mesmo comando em todas as threads (bt: imprime a pilha de chamadas) - [gcore(1) — Linux manual page](https://man7.org/linux/man-pages/man1/gcore.1.html) · gdb · Gera um core file do programa em execução, e o programa continua rodando normalmente depois #### sp-sync-call · Chamadas síncronas na thread do jogo · Synchronous DB / file I/O on the game loop Se o tick espera uma resposta do BD ou uma escrita em arquivo, todo o andamento do jogo no servidor para por esse tempo. - Por quê → Efeito → Na tela: Dentro do tick, espera consultas e gravações no BD, escrita de log e chamadas a APIs externas → Se o BD leva 100 ms, o tick também fica parado 100 ms → Toda vez que o BD ou o disco fica lento, o mapa inteiro dá um engasgo - Sintomas: Travamento, Engasgos / Fatores: Paralisação - Quem: Local ou canal específico, Servidor inteiro / Quando: Ao fazer ações específicas, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Passar todo trabalho lento (consultas e gravações no BD, escrita de log, chamadas a APIs externas) para execução assíncrona e aplicar o resultado no tick seguinte (só colocar timeout não basta: enquanto espera, o tick continua parado). - Números de referência: Mesmo uma ida e volta de 0,5 ms ao BD no mesmo data center, chamada 100 vezes num tick, soma 50 ms. Sozinha, consome o orçamento inteiro de 20 ticks. - No gráfico: Picos aleatórios (Tempo de tick do servidor, latência das queries do BD) - Onde olhar: Gráfico de tempo de tick, latência das queries do BD (slow query log etc.) e latência do disco no mesmo eixo de tempo. Sem métrica de tick, onde a thread do jogo espera, com bcc offcputime -p - Confirma se: Os picos de tick coincidem com os picos de latência do BD ou de arquivos, e o tempo de espera da thread do jogo se concentra nas pilhas de recebimento de resposta do BD ou de escrita em arquivo - Descarta se: Latência do BD e do disco tranquila, mas o tick dá picos: pausa do GC ou contenção de lock - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Designs, Lessons and Advice from Building Large Distributed Systems](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Keynote do LADIS 2009 (Jeff Dean). Ida e volta dentro do mesmo data center de cerca de 0,5 ms (500.000 ns) - [ASP.NET Core Best Practices](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/best-practices) · Microsoft · Chamar de forma assíncrona acesso a dados, I/O e operações demoradas; chamadas síncronas bloqueantes levam ao esgotamento do pool de threads e a respostas lentas - [Demonstrations of offcputime, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/offcputime_example.txt) · IO Visor · Soma, por pilha de chamadas, o tempo em que as threads ficaram paradas fora da CPU (off-CPU); -p especifica o processo #### sp-queue · Acúmulo na fila de mensagens · Mailbox / job queue backlog Quando os pedidos chegam mais rápido do que são processados e se acumulam na fila, os últimos da fila só são processados segundos depois ou são descartados. - Por quê → Efeito → Na tela: Os pedidos chegam mais rápido do que são processados → A fila cresce e, ao passar do limite, os pedidos são descartados → Skills e trocas respondem com atraso ou não saem - Sintomas: Input lag, Ação perdida / rollback / Fatores: Latência, Perda de pacotes - Quem: Local ou canal específico, Só um recurso específico / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Monitorar o tamanho da fila, ter uma política que descarta primeiro os pedidos velhos, paralelizar o processamento. - No gráfico: Achata ao bater no limite (Tamanho da fila e idade da mensagem mais antiga, processados por segundo) - Onde olhar: O que o servidor registra por fila: tamanho, idade da mensagem mais antiga, mensagens recebidas, processadas e descartadas por segundo. Sem métricas no código, o Recv-Q do socket do jogo (o que o kernel recebeu e o processo ainda não leu) com ss (ou netstat) - Confirma se: Enquanto as chegadas superam o processamento, os processados por segundo não passam de um certo valor, e o tamanho e a idade da fila e os descartes não param de subir - Descarta se: Fila curta e mensagens novas, mas a resposta demora: latência da conexão ou atraso do próprio tick - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Casos reais: eve-hedgp-2014 - Fontes: - [Avoiding insurmountable queue backlogs](https://d1.awsstatic.com/builderslibrary/pdfs/avoiding-insurmountable-queue-backlogs.pdf) · AWS · Amazon Builders' Library. Monitorar o acúmulo pela idade das mensagens na fila; sistemas em tempo real processam primeiro os dados novos (mais perto de LIFO) e às vezes descartam mensagens antigas - [Site Reliability Engineering, Chapter 22: Addressing Cascading Failures](https://sre.google/sre-book/addressing-cascading-failures/) · Google · Quando os pedidos chegam mais rápido que o processamento, a fila enche e a latência sobe; trocar o FIFO por LIFO ou CoDel tira da fila os pedidos antigos que já perderam a utilidade - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · Ferramenta que mostra estatísticas de sockets (informações parecidas com as do netstat); -p mostra o processo que usa o socket - [netstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/netstat.8.html) · net-tools · Recv-Q: número de bytes em um socket conectado que o programa do usuário ainda não leu #### sp-timer-burst · Timers disparando todos ao mesmo tempo · Synchronized timers Se todos os respawns de monstros, todas as expirações de buff e as recompensas da hora cheia caem no mesmo tick, aquele tick fica dezenas de vezes mais pesado. - Por quê → Efeito → Na tela: Timers de respawn, expiração, recompensa e salvamento automático alinhados no mesmo horário → Dezenas de vezes o trabalho normal naquele único tick → Um engasgo a cada horário fixo - Sintomas: Travamento, Engasgos / Fatores: Paralisação - Quem: Local ou canal específico, Servidor inteiro / Quando: Em intervalos regulares - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Espalhar um pouco os horários dos timers de forma aleatória, dividir o processamento entre vários ticks. - No gráfico: Picos em intervalos regulares (Tempo de tick do servidor) - Onde olhar: Juntar os horários dos picos de tick e ver os intervalos (hora cheia, a cada 5 minutos etc.). Comparar com a lista de timers de respawn, expiração de buff, recompensa e salvamento automático que rodam no mesmo horário - Confirma se: O tick dá pico sempre no mesmo horário ou no mesmo intervalo, e nesse horário há tarefas de timer do jogo que disparam todas juntas - Descarta se: Há periodicidade, mas coincide com as pausas no log do GC ou com o horário de cron e backup do servidor: pausa stop-the-world do GC no servidor ou tarefas agendadas - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Timeouts, retries, and backoff with jitter](https://d1.awsstatic.com/builderslibrary/pdfs/timeouts-retries-and-backoff-with-jitter.pdf) · AWS · Amazon Builders' Library. Acrescentar jitter a todos os timers, tarefas periódicas e tarefas adiadas espalha a carga que se concentraria no mesmo instante; caso em que os pedidos de 1 em 1 minuto de vários servidores se concentravam nos primeiros segundos de cada minuto #### sp-pathfinding · Tempestade de pathfinding · Pathfinding storms Quando centenas de monstros perseguem jogadores ao mesmo tempo calculando rotas, o consumo de CPU é grande. - Por quê → Efeito → Na tela: Pull em massa ou spawns grandes fazem muitos monstros perseguirem jogadores ao mesmo tempo → Cálculo de pathfinding para cada monstro → Câmera lenta só naquela área de caça - Sintomas: Câmera lenta / Fatores: Paralisação - Quem: Local ou canal específico / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cachear rotas, limitar o número de cálculos, dividir entre vários ticks. - No gráfico: Sobe com a carga (Tempo de tick do servidor, monstros por zona) - Onde olhar: Número de monstros perseguindo jogadores e tempo de tick por zona. Sem essa contagem, a fatia de CPU por função do processo do jogo com perf top -p - Confirma se: O tempo de tick sobe durante pulls em massa ou spawns grandes, e as funções de pathfinding (busca de rota) ocupam boa parte do tempo de CPU - Descarta se: Poucos monstros e muitos jogadores, e o tick sobe: cálculo de visibilidade ou broadcast - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [AI.NavMesh.pathfindingIterationsPerFrame](https://docs.unity3d.com/ScriptReference/AI.NavMesh-pathfindingIterationsPerFrame.html) · Unity · Processa o pathfinding só até um número fixo de nós por frame, dividindo o trabalho entre vários frames, para o jogo continuar fluido mesmo com rotas longas ou muitos pedidos de uma vez - [perf-top(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-top.1.html) · perf · Mostra em tempo real a fatia de uso de CPU por função (símbolo) de um processo em execução (-p) #### sp-serialize · Custo de serialização e compressão · Serialization / compression cost Converter os dados a enviar em bytes e comprimi-los também gasta CPU, e com muitos jogadores esse custo explode. - Por quê → Efeito → Na tela: Cada atualização converte estruturas em bytes e as comprime → O custo cresce com o quadrado do número de jogadores → O envio atrasa: input lag - Sintomas: Input lag / Fatores: Paralisação, Latência - Quem: Local ou canal específico / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Reutilizar para vários jogadores o pacote montado uma vez, usar um formato leve. - No gráfico: Sobe com a carga (Uso de CPU do servidor, CPU da thread que monta os pacotes) - Onde olhar: Comparar com perf top -p a fatia das funções de serialização, compressão e criptografia (incluindo funções de bibliotecas como zlib, LZ4 e OpenSSL) no tempo de CPU do processo do jogo, com poucos jogadores e com o servidor lotado - Confirma se: Quanto mais lota, maior a fatia das funções de serialização, compressão e criptografia, e a CPU da thread que monta os pacotes satura primeiro - Descarta se: Fatia pequena dessas funções: cálculo de visibilidade ou lógica do jogo - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Em conexões que criptografam os pacotes (TLS, DTLS etc.), criptografar e descriptografar também gasta CPU. A criptografia é feita separadamente em cada conexão, então, mesmo reutilizando para vários jogadores o pacote montado uma vez, o custo de criptografia se multiplica pelo número de destinatários. Cifras simétricas como AES-GCM são tão rápidas que um núcleo processa vários GB por segundo, e normalmente pesam pouco, mas a velocidade varia muito com o tamanho da unidade criptografada de cada vez (o registro), e em jogos, com muitos pacotes pequenos, o custo por byte aumenta. No handshake, feito uma vez por conexão, o servidor assina com a chave do certificado e calcula a troca de chaves (ECDHE). Um núcleo faz por segundo de cerca de 1.100 (RSA 2048) a 18 mil (ECDSA P-256) assinaturas e cerca de 9 mil trocas de chaves, o que pesa quando chega uma avalanche de logins. - Fontes: - [Introduction to Iris in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/introduction-to-iris-in-unreal-engine) · Epic Games · Mantém uma única cópia quantizada do estado a replicar, o que reduz o trabalho pesado e permite que várias conexões compartilhem esse trabalho - [VALORANT's 128-Tick Servers](https://www.riotgames.com/en/news/valorants-128-tick-servers) · Riot Games · Comparar as variáveis replicadas de cada cliente a cada frame e empacotar os valores alterados é um trabalho lento, que lê memória espalhada, e consome muita CPU do servidor - [How "expensive" is crypto anyway?](https://blog.cloudflare.com/how-expensive-is-crypto-anyway/) · Cloudflare · Medição com BoringSSL: AES-128-GCM a cerca de 3,7 GB por segundo (varia muito com o tamanho do registro); um núcleo faz por segundo 1.120 assinaturas RSA 2048, 18.477 assinaturas ECDSA P-256 e 9.394 ECDHE P-256; nos servidores de borda da Cloudflare, as bibliotecas TLS usaram cerca de 1,8% da CPU - [perf-top(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-top.1.html) · perf · Mostra em tempo real a fatia de uso de CPU por função (símbolo) de um processo em execução (-p) #### sp-crash · Crash do servidor · Server process crash Quando um erro não tratado derruba o processo do servidor, todos que estavam naquele servidor são desconectados ao mesmo tempo. - Por quê → Efeito → Na tela: Erro fatal, como referência a algo que não existe (referência nula), dados inválidos ou falta de memória → O processo do servidor (ou da zona) termina → Desconexão de todos ao mesmo tempo, e o progresso desde o último salvamento pode sofrer rollback - Sintomas: Desconexão, Ação perdida / rollback / Fatores: Paralisação - Quem: Local ou canal específico, Servidor inteiro / Quando: Aleatoriamente, de vez em quando, Ao fazer ações específicas - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Analisar os crash dumps e corrigir a causa, salvar com frequência. - O que fazer (Equipe de infraestrutura): Reiniciar o processo automaticamente, ter um ambiente para coletar e guardar crash dumps, alertar na hora quando o servidor cair. - No gráfico: Queda de conexões em massa (Conexões, número de reinícios do processo) - Onde olhar: Registros de core dump no coredumpctl list (horário, PID, sinal de término) e registros de término anormal e reinício no gerenciador de serviços (systemd). Em servidores Windows, os arquivos de dump gerados pelo WER - Confirma se: No momento em que o número de conexões cai de repente para perto de 0, há um término anormal do processo do servidor do jogo e um core dump - Descarta se: O processo continua vivo, mas as conexões caíram: aponta para equipamentos de rede ou timeout de inatividade. Registro de reinício pelo watchdog após uma parada longa: aponta para loop infinito ou deadlock - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Collecting User-Mode Dumps](https://learn.microsoft.com/en-us/windows/win32/wer/collecting-user-mode-dumps) · Microsoft · Configura o Relatório de Erros do Windows (WER) para coletar localmente dumps completos ou mini dumps quando um programa em modo de usuário sofre crash - [systemd.service(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd.service.5.html) · systemd · Restart=on-failure reinicia o serviço automaticamente em término anormal, término por sinal (incluindo core dump) ou estouro do tempo do watchdog; recomendado para serviços de longa duração - [coredumpctl(1) — Linux manual page](https://man7.org/linux/man-pages/man1/coredumpctl.1.html) · systemd · Consulta com list os core dumps salvos pelo systemd-coredump, mostrando horário do crash, PID e o sinal que causou o crash #### sp-threadpool · Esgotamento do pool de threads · Thread pool starvation Quando todas as worker threads que processam tarefas ficam presas em trabalhos lentos, os pedidos novos ficam esperando indefinidamente. - Por quê → Efeito → Na tela: As worker threads ficam presas esperando resposta de APIs externas ou do BD → Não há thread livre para os pedidos novos → Loading infinito em recursos específicos, como login ou loja - Sintomas: Não conecta / loading infinito, Input lag, Travamento / Fatores: Paralisação - Quem: Só um recurso específico, Servidor inteiro / Quando: Quando junta muita gente, Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Pôr timeout nas chamadas lentas, separar pools de threads por recurso, tornar as chamadas assíncronas. - No gráfico: Achata ao bater no limite (Threads e tamanho da fila do pool de threads, tempo de processamento dos pedidos) - Onde olhar: No .NET, ver o número de threads e o tamanho da fila do pool de threads no dotnet-counters monitor (dotnet.thread_pool.thread.count e dotnet.thread_pool.queue.length a partir do .NET 9, ThreadPool Thread Count e ThreadPool Queue Length até o 8) e conferir com dotnet-stack onde as worker threads estão esperando. Em servidores JVM ou nativos, conferir o mesmo com thread dumps - Confirma se: O uso de CPU fica bem abaixo de 100%, mas o número de threads sobe devagar sem parar ou fica colado no teto, a fila acumula e a maioria dos workers espera a resposta da mesma chamada externa (BD, HTTP) - Descarta se: Fila vazia e mesmo assim lento: o próprio destino das chamadas está lento, então aponta para falha em cascata ou dependência de serviços externos - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Se o recebimento de pacotes e a lógica do jogo dividem o mesmo pool de worker threads, basta algumas tarefas lentas ocuparem todos os workers para o processamento de pacotes do servidor inteiro parar. - Casos reais: riot-euw-2021 - Fontes: - [Debug ThreadPool Starvation](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/debug-threadpool-starvation) · Microsoft · Quando não sobra thread no pool e as tarefas novas esperam, a resposta fica lenta; a causa é código bloqueante que segura threads. No dotnet-counters, CPU bem abaixo de 100% com dotnet.thread_pool.thread.count subindo devagar sem parar é sinal de esgotamento (muitas vezes dotnet.thread_pool.queue.length também está alto); dotnet-stack mostra onde as threads esperam - [Avoiding insurmountable queue backlogs](https://d1.awsstatic.com/builderslibrary/pdfs/avoiding-insurmountable-queue-backlogs.pdf) · AWS · Concorrência = taxa de chegada × latência (lei de Little). Com 100 pedidos por segundo, se a latência sobe de 100 ms para 10 s, as threads necessárias passam de 10 para 1.000 e o pool se esgota - [Bulkhead Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead) · Microsoft Azure · Com um pool de conexões e de threads separado para cada destino, a falha de um destino bloqueia só aquele pool - [.NET runtime metrics](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/built-in-metrics-runtime) · .NET · dotnet.thread_pool.thread.count (threads do pool) e dotnet.thread_pool.queue.length (tarefas na fila) existem a partir do .NET 9 - [Well-known EventCounters in .NET](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/available-counters) · Microsoft · ThreadPool Thread Count (threadpool-thread-count) e ThreadPool Queue Length (threadpool-queue-length) do .NET 8 e anteriores #### sp-infinite-loop · Loop infinito e lógica descontrolada · Infinite loop / runaway logic Quando um bug impede um tick de terminar, o servidor para e o watchdog o reinicia à força. - Por quê → Efeito → Na tela: Uma condição errada faz um loop nunca terminar, ou uma recursão sai do controle → O tick não termina e o servidor para → Travamento e depois desconexão de todos - Sintomas: Travamento, Desconexão / Fatores: Paralisação - Quem: Local ou canal específico, Servidor inteiro / Quando: Ao fazer ações específicas, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Limitar o número de iterações, ter um watchdog, testar reproduzindo a entrada problemática. - No gráfico: Queda de conexões em massa (Conexões, CPU por thread) - Onde olhar: Durante a parada, ver a CPU por thread com pidstat -t 1 e conferir com perf top -t (ID da thread) ou com gdb em que função a thread a 100% está rodando. Se o processo já reiniciou, procurar registros de estouro do tempo do watchdog (WatchdogSec do systemd, falha da liveness probe do Kubernetes) - Confirma se: Enquanto o servidor está parado, uma thread do jogo fica colada em 100% de CPU, e a pilha continua girando dentro da mesma função ou do mesmo loop - Descarta se: CPU perto de 0 durante a parada: aponta para deadlock ou espera de resposta externa - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [systemd.service(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd.service.5.html) · systemd · WatchdogSec=: se o serviço não envia o sinal de vida (WATCHDOG=1) dentro do tempo definido, é considerado em falha e encerrado, com reinício automático conforme a configuração Restart= - [Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/workloads/pods/probes/) · Kubernetes · A liveness probe detecta um estado em que o processo roda, mas não avança, e reinicia; por padrão, verifica a cada 10 s e reinicia após 3 falhas seguidas - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -t mostra também as estatísticas por thread do processo (uso de CPU etc.) - [perf-top(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-top.1.html) · perf · Mostra em tempo real a fatia de uso de CPU por função (símbolo) de uma thread (-t) ou processo (-p) em execução #### sp-hot-entity · Combate concentrado em um só alvo (world boss) · Hot entity / combat event fan-out Quando centenas de jogadores atacam o mesmo boss ao mesmo tempo, o cálculo daquele boss se concentra num só ponto, e as informações de cada golpe vão para todos que estão vendo. - Por quê → Efeito → Na tela: Centenas de jogadores usam skills, buffs e debuffs sem parar num único boss → Os cálculos de vida, lista de aggro e debuffs do boss se concentram num só ponto, e cada golpe envia pacotes de números de dano e efeitos para todos que estão vendo → As skills entram atrasadas, os números de dano aparecem todos de uma vez, câmera lenta só em volta do boss - Sintomas: Input lag, Avanço rápido, Câmera lenta / Fatores: Paralisação, Latência - Quem: Local ou canal específico / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Agrupar ou omitir os números de dano e efeitos dos outros jogadores, limitar o número de debuffs num mesmo alvo, dividir o processamento dos golpes entre vários ticks. - Números de referência: 800 jogadores batendo 2 vezes por segundo dão 1.600 golpes por segundo. Avisar os 800 que estão vendo dá 1,28 milhão de mensagens por segundo. - No gráfico: Sobe com a carga (Tempo de tick do servidor, mensagens enviadas) - Onde olhar: Tempo de tick e pacotes enviados no horário da luta contra o boss, junto com o número de jogadores em volta do boss e, se possível, eventos por segundo (golpes, buffs, debuffs) por alvo - Confirma se: Quando aumenta o número de jogadores em volta do boss, o tempo de tick e o volume enviado sobem de forma íngreme, e o boss tem dezenas de vezes mais eventos por segundo que os outros alvos - Descarta se: Fica igualmente lento só por juntar gente num lugar, sem relação com o boss: cálculo de visibilidade ou explosão de broadcast - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [HED-GP Technical Retrospective: What a HED-ache](https://www.eveonline.com/news/view/what-a-hed-ache) · CCP Games · Até um único ataque precisa ser avisado a todos os clientes que estão vendo, o que gera um custo O(n²) (n jogadores avisando n jogadores); ataques de drones, com muitas mensagens, fazem esse custo crescer ainda mais rápido #### sp-spawn-burst · Avalanche de spawns ao entrar em área lotada · Spawn burst when entering a crowd Quando o jogador se teletransporta para uma cidade lotada, o servidor precisa enviar de uma vez a aparência, o equipamento e o estado das centenas de jogadores que acabaram de entrar no campo de visão. - Por quê → Efeito → Na tela: Teletransporte, login ou troca de canal fazem o jogador aparecer de repente num lugar lotado → O servidor monta e envia de uma vez os dados completos de centenas de jogadores, e seu PC também carrega tudo de uma vez → Uma pausa curta logo ao chegar, personagens aparecendo com atraso, um por um, e comandos respondendo com atraso - Sintomas: Travamento, Input lag, Avanço rápido / Fatores: Paralisação, Latência - Quem: Só eu, Local ou canal específico / Quando: Em movimento ou ao trocar de mapa, Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: enviar em ordem de proximidade, dividindo entre vários ticks, cachear os dados de aparência. Cliente: receber antecipadamente durante a tela de carregamento, criar os personagens recebidos aos poucos ao longo de vários frames. - Números de referência: Se os dados de aparência, equipamento e buffs de um jogador têm 300 bytes, 500 jogadores dão cerca de 150 KB. Dezenas de vezes o volume normal de um tick (alguns KB) chegam num instante. - No gráfico: Pico logo após abrir ou manutenção (Bytes enviados por conexão, frame time do cliente) - Onde olhar: Bytes e pacotes enviados naquela conexão nos primeiros segundos após chegar a um lugar lotado (log do servidor) e frame time do cliente (net graph, log do cliente) - Confirma se: Logo após a chegada, o volume enviado naquela conexão dispara para dezenas de vezes o de um tick normal e depois baixa, e no mesmo instante o frame time do cliente também dá pico - Descarta se: O mesmo travamento acontece ao ir para um lugar vazio: aponta para troca de mapa (transferência entre servidores) ou carregamento no cliente - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Detailed Actor Replication Flow in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/detailed-actor-replication-flow-in-unreal-engine) · Epic Games · Ao abrir pela primeira vez um canal de ator, envia junto dados como posição e rotação iniciais; quando a conexão satura, os atores restantes ficam para o próximo tick - [Actor Priority in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-priority-in-unreal-engine) · Epic Games · Prioriza por distância e direção do olhar, enviando primeiro os atores próximos e visíveis #### sp-entity-buildup · Acúmulo de entidades (itens e invocações não removidos) · Entity / timer buildup over uptime Quando itens no chão, invocações e timers encerrados que deveriam sumir não são limpos e se acumulam, quanto mais tempo o servidor fica ligado, mais trabalho cada tick tem. - Por quê → Efeito → Na tela: Itens no chão, invocações, timers expirados e dados de parties vazias não são removidos a tempo → A lista percorrida a cada tick fica mais longa a cada dia → Logo após a manutenção tudo vai bem, mas depois de alguns dias só aquele servidor ou área fica cada vez mais lento - Sintomas: Câmera lenta, Engasgos, Input lag / Fatores: Paralisação - Quem: Servidor inteiro, Local ou canal específico / Quando: Quanto mais tempo ligado - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Registrar o número de entidades por área como métrica e acompanhar a tendência, definir tempo de vida e limite de quantidade para cada entidade, fazer limpezas periódicas. - Números de referência: Num servidor que percorre todas as entidades uma vez por tick, quando o número de entidades dobra, o tempo de tick dessa parte também dobra. - No gráfico: Dente de serra (Entidades por zona, tempo de tick do servidor) - Onde olhar: Número de entidades (itens no chão, invocações, timers) e tempo de tick por zona e servidor, num período mais longo que o ciclo de manutenção (algumas semanas) - Confirma se: O número de entidades e o tempo de tick começam baixos após a manutenção, sobem a cada dia e despencam na manutenção ou no reinício, repetidamente, e a memória fica com folga o tempo todo - Descarta se: Tick estável, mas a memória não para de subir: aponta para vazamento de memória - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Como no vazamento de memória, piora quanto mais tempo o servidor fica ligado. A diferença é que a memória está com folga e só o tempo de tick aumenta. Se o gráfico do número de entidades tem formato de dente de serra a cada ciclo de manutenção, é este o caso. - Fontes: - [Actor Ticking in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-ticking-in-unreal-engine) · Epic Games · Atores e componentes rodam o tick uma vez por frame, a menos que se defina outro intervalo, e o tick pode ser desligado quando não é necessário - [AActor::SetLifeSpan](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Engine/AActor/SetLifeSpan) · Epic Games · Com um tempo de vida definido, o ator é destruído automaticamente quando ele expira #### sp-patch-traffic · Mudança no padrão de tráfego após um patch · Patch changes traffic pattern Quando novos conteúdos, efeitos e campos sincronizados aumentam o tamanho e a frequência dos pacotes, um servidor que ia bem passa a bater nos limites de MTU, largura de banda e número de pacotes depois do patch. - Por quê → Efeito → Na tela: O patch acrescenta efeitos de skill, campos sincronizados e dados de itens, e os pacotes ficam maiores ou mais frequentes → Pacotes grandes passam do MTU e são fragmentados, e o volume a mais esbarra na largura de banda, no limite de PPS da nuvem e no buffer de envio → Desde o patch, teleporte, skills que não saem e input lag nos lugares lotados. A infraestrutura não mudou nada, mas a perda aumenta - Sintomas: Teleporte, Ação perdida / rollback, Input lag / Fatores: Perda de pacotes, Latência - Quem: Servidor inteiro, Local ou canal específico, Região ou operadora específica / Quando: Quando junta muita gente, Horário de pico à noite, Sempre - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Dividir os pacotes no próprio jogo em até 1.200 bytes, enviar só as mudanças dos novos campos sincronizados e reduzir a frequência conforme a distância e a importância, antes do deploy comparar no servidor de testes os pacotes e bytes por segundo por jogador e o tamanho do maior pacote com o build anterior, registrar a versão do build nas métricas de tráfego. - O que fazer (Equipe de infraestrutura): Servidores/SO: marcar o horário do deploy nos gráficos e comparar pacotes e bytes por segundo por jogador e o tamanho médio dos pacotes antes e depois do deploy, alertar com os contadores de limite excedido da instância, passar para uma instância maior se necessário. Rede: verificar os limites de processamento de firewalls, load balancers e equipamentos de proteção contra DDoS e se eles bloqueiam fragmentos. - Números de referência: Pacotes UDP de até 1.200 bytes são seguros; o MTU dos caminhos na internet costuma ser 1.500 bytes, e é menor ao passar por túneis (1.476 bytes num túnel GRE). Pacotes acima do MTU do caminho são fragmentados ou descartados, e um pacote fragmentado se perde inteiro quando um único fragmento se perde. Se os pacotes por segundo de cada jogador sobem 20%, os do servidor inteiro também sobem 20%, e uma instância que já trabalhava perto do limite transborda na hora. - No gráfico: Degrau a partir de um momento (Pacotes e bytes por segundo por jogador, tamanho médio dos pacotes) - Onde olhar: Pacotes e bytes por segundo da NIC do servidor antes e depois do horário do deploy (rxpck/s, txpck/s, rxkB/s e txkB/s do sar -n DEV; no EC2, NetworkPacketsOut e NetworkOut), divididos pelo número de jogadores simultâneos. Tamanho médio dos pacotes = bytes ÷ pacotes; distribuição de tamanhos com a estatística Packet Lengths do Wireshark sobre uma captura de pacotes - Confirma se: Logo após o deploy, os pacotes e bytes por jogador ou o tamanho médio dos pacotes sobem um degrau e ficam lá, e a partir do mesmo momento sobem os fragmentos criados pelo servidor (fragcrt/s do sar -n IP) ou os contadores de limite excedido da instância (pps_allowance_exceeded e bw_out_allowance_exceeded do ENA da AWS) - Descarta se: Padrão de tráfego igual antes e depois do deploy, mas só a latência e a perda aumentaram: verificar mudanças de infraestrutura no mesmo horário (configuração, rotas, equipamentos, atualização de SO e kernel) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Quando chega um report de que “antes do patch estava bom”, esta é a causa do lado do jogo a verificar primeiro, junto com as mudanças de infraestrutura. Mesmo sem mudanças de rede nas notas do patch, um único efeito ou campo sincronizado novo se multiplica por centenas de jogadores nos lugares lotados. Onde o tráfego extra de fato esbarra é tratado nos verbetes “Fragmentação IP de pacotes UDP”, “Limite de PPS da nuvem excedido”, “Saturação da largura de banda da NIC”, “Buffer de socket do kernel insuficiente” e “Sobrecarga de equipamento intermediário (firewall, IPS, proteção contra DDoS)”. Este verbete cobre o caso em que o ponto de partida que levou a esses limites foi o patch do jogo, então reduza o tráfego que o patch acrescentou antes de aumentar os limites. Se o SO e o kernel também foram atualizados no mesmo horário, veja se o tráfego por jogador mudou para separar este caso de “Mudança de desempenho após atualização de SO, kernel, driver ou firmware”. - Fontes: - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · Apps UDP não devem enviar datagramas maiores que o MTU do caminho (SHOULD NOT); perder um fragmento faz perder o pacote fragmentado inteiro, e alguns NATs e firewalls descartam todos os fragmentos - [RFC 8899: Packetization Layer Path MTU Discovery for Datagram Transports](https://www.rfc-editor.org/rfc/rfc8899) · IETF · Recomenda 1.200 bytes como tamanho seguro padrão (BASE_PLPMTU) para transportes de datagramas como o UDP - [Maximum transmission unit and maximum segment size](https://developers.cloudflare.com/magic-transit/reference/mtu-mss/) · Cloudflare · MTU do caminho na internet de 1.500; ao passar por um túnel GRE, 1.476 - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · pps_allowance_exceeded e bw_out_allowance_exceeded: número de pacotes enfileirados ou descartados por passar dos limites de PPS e de largura de banda de envio da instância - [sar(1) — Linux manual page](https://man7.org/linux/man-pages/man1/sar.1.html) · sysstat · rxpck/s e txpck/s (pacotes por segundo) e rxkB/s e txkB/s (KB por segundo) do sar -n DEV; fragcrt/s do sar -n IP (fragmentos IP criados por segundo, ipFragCreates) - [CloudWatch metrics that are available for your instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) · AWS · NetworkPacketsOut (pacotes enviados pela instância por todas as interfaces de rede) e NetworkOut (bytes enviados) - [8.7. Packet Lengths](https://www.wireshark.org/docs/wsug_html_chunked/ChStatPacketLengths.html) · Wireshark · Divide os pacotes capturados em faixas de tamanho e mostra quantidade, média, mínimo e máximo ### L10 Memória (9 causas) #### mem-gc · Pausa stop-the-world do GC no servidor · Stop-the-world GC pause Para coletar o lixo, um servidor em Java ou C# interrompe todas as threads (stop-the-world), e o servidor inteiro fica parado enquanto isso dura. - Por quê → Efeito → Na tela: O heap enche e o GC começa → Todas as threads do jogo param durante a coleta (quanto mais dados vivos, mais demora) → Travamento para todos no servidor ao mesmo tempo, seguido de avanço rápido - Sintomas: Travamento, Avanço rápido / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Em intervalos regulares, Quanto mais tempo ligado - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Definir explicitamente nas opções de inicialização um GC de pausas curtas (ZGC, Shenandoah ou G1 com meta de pausa menor), reduzir alocações, ajustar o tamanho do heap. - O que fazer (Equipe de infraestrutura): Usar instâncias com memória suficiente para um heap folgado, dar aos contêineres pelo menos 2 CPUs e cerca de 1,8 GB de memória (abaixo disso, o JDK 26 e anteriores escolhem o Serial GC como padrão), monitorar o tempo de pausa do GC. - Números de referência: O Minor GC, que coleta só os objetos novos (geração young), leva de alguns a dezenas de ms. O Full GC, que coleta o heap inteiro com vários GB de dados vivos, pode passar de 1 s. O ZGC fica abaixo de 1 ms quase independentemente do tamanho do heap, e o Shenandoah também tem pausas curtas, que não crescem com o tamanho do heap. - No gráfico: Picos em intervalos regulares (Tempo de tick do servidor, tempo de pausa do GC) - Onde olhar: Ativar o log do GC e sobrepor o horário e a duração de cada pausa ao gráfico de tempo de tick do servidor. No Java, as linhas Pause da opção de inicialização -Xlog:gc* (-XX:+PrintGCDetails no JDK 8 e anteriores); no .NET, a métrica de pausa do GC no dotnet-counters (dotnet.gc.pause.time a partir do .NET 9, % Time in GC since last GC no 8 e anteriores); no Go, a linha que o GODEBUG=gctrace=1 registra a cada GC - Confirma se: Os picos de tick coincidem com as pausas do GC, e a duração da pausa é parecida com a do pico. Todas as zonas e canais do servidor dão pico no mesmo instante - Descarta se: Picos de tick sem pausas longas no log do GC: outra causa, como lock, chamada síncrona ou escrita em disco. Só uma zona dá pico: GC da engine de script (mem-script-gc) ou carga daquela zona - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: No Java, a meta padrão de cada pausa do G1 é 200 ms, o que equivale a 4 ticks em um servidor de 20 ticks. Se o contêiner recebe menos de 2 CPUs ou menos de cerca de 1,8 GB de memória, o Java do JDK 26 e anteriores escolhe como padrão o Serial GC, que coleta com uma única thread, e as pausas ficam bem mais longas. Servidores em C# (.NET) costumam ativar o GC de servidor e o GC em segundo plano, mas as coletas das gerações 0 e 1 (Gen0/1), que guardam os objetos novos, e o Full GC com compactação continuam parando todas as threads. No Go, as pausas costumam ficar abaixo de 1 ms, mas, com muita alocação, quem pede memória precisa assumir parte do trabalho do GC, e o tick fica mais lento. Em qualquer modelo, se a alocação for mais rápida que a coleta, a thread do jogo acaba parando: o G1 passa para um Full GC, e o ZGC segura a thread que pediu memória até a coleta terminar. - Casos reais: riot-euw-2021 - Fontes: - [Garbage-First (G1) Garbage Collector](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-first-g1-garbage-collector1.html) · Oracle · Meta de pausa padrão do G1 de 200 ms (MaxGCPauseMillis); se a memória acaba durante a coleta, passa para um Full GC, que para e compacta o heap inteiro - [JEP 523: Make G1 the Default Garbage Collector in All Environments](https://openjdk.org/jeps/523) · OpenJDK · Até agora, com 1 CPU ou menos de 1.792 MB de memória, o Serial GC era escolhido como padrão; a partir do JDK 27, o G1 é o padrão em qualquer ambiente - [JEP 439: Generational ZGC](https://openjdk.org/jeps/439) · OpenJDK · Pausas do ZGC de no máximo 1 ms, independentes do tamanho do heap; pausas do G1 de alguns ms a alguns segundos. Se a alocação for mais rápida que a recuperação, há risco de parada de alocação (allocation stall) - [JEP 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)](https://openjdk.org/jeps/189) · OpenJDK · O tempo de pausa do Shenandoah é parecido, seja o heap de 200 MB ou de 200 GB - [Background garbage collection](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/background-gc) · .NET · O GC em segundo plano só se aplica às coletas da geração 2; as coletas das gerações 0 e 1 (GC em primeiro plano) param todas as threads gerenciadas - [A Guide to the Go Garbage Collector](https://go.dev/doc/gc-guide) · Go · O GC do Go roda quase todo de forma concorrente e só tem pausas stop-the-world curtas; com muita alocação, as goroutines assumem parte do trabalho do GC (assist), o que gera atraso - [JEP 271: Unified GC Logging](https://openjdk.org/jeps/271) · OpenJDK · A partir do JDK 9, o log do GC foi reimplementado com o logging unificado (-Xlog); -Xlog:gc gera uma linha por GC, como o antigo -XX:+PrintGC - [The java Command](https://docs.oracle.com/en/java/javase/25/docs/specs/man/java.html) · Oracle · Tabela de conversão das opções antigas de log do GC para -Xlog: -XX:+PrintGCDetails vira -Xlog:gc* - [dotnet-counters diagnostic tool](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters) · .NET · A partir do .NET 9, aparece como medidores do System.Runtime (dotnet.gc.pause.time e outros); no .NET 8 e anteriores, como os antigos EventCounters (% Time in GC since last GC e outros) - [runtime package](https://pkg.go.dev/runtime) · Go · GODEBUG=gctrace=1: uma linha por GC, com o tempo de relógio (wall clock) de cada fase, o tamanho do heap no início e no fim do GC e o heap alvo #### mem-script-gc · Pausa do GC na engine de script · Scripting VM GC (Lua, etc.) Mesmo em um servidor em C++, se quests, IA e skills rodam em uma linguagem de script como Lua, a zona fica parada enquanto o GC da engine de script roda. - Por quê → Efeito → Na tela: Em cada zona, a engine de script executa quests, IA e eventos e cria objetos temporários em grande quantidade → Quando o GC da engine de script coleta muita coisa de uma vez, o tick daquela zona para → Engasgos periódicos só em certas zonas ou durante certos eventos - Sintomas: Engasgos, Travamento / Fatores: Paralisação - Quem: Local ou canal específico / Quando: Quando junta muita gente, Em intervalos regulares - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Configurar GC incremental ou geracional, avançar o GC um pouco a cada tick, reduzir os objetos temporários dos scripts. - Números de referência: Quando o heap do script cresce para centenas de MB, uma coleta feita toda de uma vez (com a coleta incremental desligada, ou a coleta completa do modo geracional) pode levar de dezenas a centenas de ms. - No gráfico: Picos em intervalos regulares (Tempo de tick por zona, memória da engine de script) - Onde olhar: Registrar a cada tick o tempo de tick por zona e o uso de memória da engine de script daquela zona (no Lua, collectgarbage("count")) e sobrepor os dois no mesmo gráfico - Confirma se: O instante em que a memória do script cai de repente (coleta toda de uma vez) coincide com o pico de tick daquela zona, e as outras zonas estão normais - Descarta se: Pico sem mudança na memória do script: carga ou lock daquela zona. Todas as zonas do servidor dão pico juntas: GC do servidor (mem-gc) ou swap (mem-swap) - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Lua 5.4 Reference Manual](https://www.lua.org/manual/5.4/manual.html) · Lua.org · O modo incremental divide a coleta em pequenos passos intercalados com a execução (passos grandes viram uma pausa stop-the-world); a coleta major do modo geracional é uma pausa stop-the-world que percorre todos os objetos; collectgarbage("count") é o total de memória usado pelo Lua (KB) #### mem-alloc · Pico de alocação · Allocation storms Quando um evento cria objetos temporários em grande quantidade, o GC roda com muito mais frequência que o normal. - Por quê → Efeito → Na tela: Drops de itens, logs de combate e recompensas de evento fazem explodir o número de objetos temporários → O GC roda várias vezes mais, e objetos que ainda não foram descartados passam para a geração old, o que também antecipa o Full GC → Engasgos periódicos só durante eventos - Sintomas: Engasgos, Travamento / Fatores: Paralisação - Quem: Servidor inteiro, Local ou canal específico / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Usar object pool e buffers reutilizáveis, fazer profiling de alocação. - No gráfico: Sobe com a carga (Número de GCs, taxa de alocação) - Onde olhar: Contar os GCs por minuto pelo log do GC (Java -Xlog:gc, Go GODEBUG=gctrace=1); no .NET, ver o volume alocado e o número de GCs no dotnet-counters (dotnet.gc.heap.total_allocated e dotnet.gc.collections a partir do .NET 9, Allocation Rate e Gen 0 GC Count no 8 e anteriores). Sobrepor ao número de jogadores simultâneos e aos horários dos eventos - Confirma se: Quando o evento começa, a taxa de alocação e o número de GCs crescem mais rápido que o número de jogadores, e as pausas curtas ficam frequentes. Quando o evento termina, tudo volta ao normal - Descarta se: Número de GCs estável, mas cada pausa mais longa: aumentaram os dados vivos (mem-gc-thrash, mem-leak) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Garbage Collector Implementation](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-collector-implementation.html) · Oracle · Quando a geração young enche, roda um minor GC; parte dos objetos sobreviventes vai para a geração old, e quando a old enche o heap inteiro é coletado (bem mais demorado que o minor); -Xlog:gc registra uma linha por GC - [A Guide to the Go Garbage Collector](https://go.dev/doc/gc-guide) · Go · Quanto maior a taxa de alocação, mais frequentes os ciclos de GC; GODEBUG=gctrace=1 gera o trace do GC - [dotnet-counters diagnostic tool](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters) · .NET · A partir do .NET 9, aparece como dotnet.gc.heap.total_allocated e dotnet.gc.collections; no .NET 8 e anteriores, como Allocation Rate e Gen 0 GC Count #### mem-leak · Vazamento de memória · Memory leak Memória que não é liberada vai se acumulando aos poucos e, depois de alguns dias, faz o GC rodar sem parar, causa swap ou leva a um encerramento forçado. - Por quê → Efeito → Na tela: Dados de personagens que já saíram do jogo e event handlers não são liberados → A memória livre diminui ao longo de vários dias → Tudo normal logo após a manutenção, mais lag a cada dia e, no fim, o servidor cai - Sintomas: Câmera lenta, Travamento, Desconexão / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Quanto mais tempo ligado, Horário de pico à noite - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Analisar heap dumps, fazer testes de carga de longa duração. - O que fazer (Equipe de infraestrutura): Monitorar a tendência do uso de memória por processo e criar alertas. - No gráfico: Subida lenta (Memória do processo (RSS), heap logo após o GC) - Onde olhar: Ver a memória do processo do servidor do jogo (RSS no pidstat -r) ao longo de vários dias e, em servidores com GC, o heap que sobra logo após o GC. No Java, o valor de depois do GC nas linhas do -Xlog:gc, que mostram o uso antes e depois; no .NET, o tamanho do heap após o GC no dotnet-counters (dotnet.gc.last_collection.heap.size a partir do .NET 9, GC Heap Size no 8 e anteriores) - Confirma se: O heap que sobra logo após o GC (linha de base) sobe a cada dia desde o reinício e não desce nem de madrugada, com poucos jogadores - Descarta se: Linha de base do heap estável, mas só o RSS sobe: fragmentação (mem-fragment) ou memória nativa. Sobe e desce com o número de jogadores: uso normal - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Com a manutenção semanal reiniciando o servidor, o vazamento fica escondido e passa muito tempo sem ser descoberto. Ele costuma aparecer de repente quando uma manutenção é adiada ou quando um evento aumenta o número de jogadores. - Fontes: - [Troubleshoot Memory Leaks](https://docs.oracle.com/en/java/javase/25/troubleshoot/troubleshooting-memory-leaks.html) · Oracle · Se a execução fica cada vez mais lenta, suspeite de vazamento; no fim a memória acaba e o processo termina de forma anormal. O principal material para analisar vazamentos é o heap dump - [Debug a memory leak in .NET](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/debug-memory-leak) · .NET · Mesmo com GC, continuar referenciando objetos desnecessários é vazamento e causa queda de desempenho e OutOfMemoryException. Verificação da tendência de memória e análise de dumps - [Garbage Collector Implementation](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-collector-implementation.html) · Oracle · As linhas do -Xlog:gc têm o formato “uso antes do GC->uso depois do GC (tamanho do heap)” - [dotnet-counters diagnostic tool](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters) · .NET · A partir do .NET 9, aparece como dotnet.gc.last_collection.heap.size; no .NET 8 e anteriores, como GC Heap Size - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -r: RSS por processo (memória realmente carregada na RAM) e page faults #### mem-gc-thrash · GC thrashing (pouca folga no heap) · GC thrashing (heap nearly full) Quando os dados vivos chegam perto do limite do heap, o GC roda, mas quase não tem o que recuperar, e passa a se repetir sem parar. - Por quê → Efeito → Na tela: Mais jogadores em um evento, ou um vazamento, enchem o heap de dados vivos até perto do limite → O GC recupera pouco e logo roda outro Full GC; o GC consome a maior parte da CPU → Todos no servidor alternam entre câmera lenta e travamento por vários minutos, até o processo ser encerrado por falta de memória - Sintomas: Câmera lenta, Travamento, Desconexão / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Horário de pico à noite, Quando junta muita gente, Quanto mais tempo ligado - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Dimensionar o heap com folga em relação aos dados vivos no pico (em geral, 2 vezes ou mais), reduzir dados referenciados por muito tempo e vazamentos. - O que fazer (Equipe de infraestrutura): Criar alerta para a proporção de tempo gasto em GC, reiniciar logo sem esperar que o servidor se recupere sozinho, usar instâncias com memória de sobra para poder aumentar o heap. - Números de referência: Em geral, considera-se sinal de perigo quando o GC passa de 10% do tempo de execução. Alguns GCs do Java geram erro de falta de memória quando gastam 98% do tempo em GC e quase não recuperam nada. - No gráfico: Achata ao bater no limite (Heap logo após o GC, proporção de tempo em GC) - Onde olhar: Ver o quanto o heap que sobra logo após o GC está perto do heap máximo e a proporção de tempo gasto em GC. No Java, o valor “depois do GC (tamanho do heap)” nas linhas do -Xlog:gc e a frequência das linhas Pause Full; no .NET, o dotnet-counters (% Time in GC since last GC no .NET 8 e anteriores, aumento de dotnet.gc.pause.time a partir do .NET 9); no Go, o intervalo entre as linhas do GODEBUG=gctrace=1 - Confirma se: Mesmo logo após o GC, o heap continua perto do máximo, os Full GCs rodam um atrás do outro e a proporção de tempo em GC sobe bem acima do normal (em geral, mais de 10%). Enquanto isso, o tick do servidor inteiro fica mais lento - Descarta se: Heap com folga logo após o GC, mas pausas longas: tipo ou configuração do GC (mem-gc) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [The Parallel Collector](https://docs.oracle.com/en/java/javase/25/gctuning/parallel-collector1.html) · Oracle · O GC paralelo lança OutOfMemoryError se gastar mais de 98% do tempo total em GC e recuperar menos de 2% do heap - [Garbage-First Garbage Collector Tuning](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-first-garbage-collector-tuning.html) · Oracle · Por padrão (GCTimeRatio=12), o G1 dimensiona o heap para manter o tempo de GC em no máximo cerca de 8% do total; Full GCs causados por ocupação alta demais do heap aparecem no log como Pause Full (G1 Compaction Pause) - [A Guide to the Go Garbage Collector](https://go.dev/doc/gc-guide) · Go · Com o padrão GOGC=100, o heap alvo é cerca de 2 vezes o heap vivo; perto do limite de memória, o GC roda sem parar (thrashing); GODEBUG=gctrace=1 gera o trace do GC - [Garbage Collector Implementation](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-collector-implementation.html) · Oracle · As linhas do -Xlog:gc mostram o tipo de GC (Pause Young, Pause Full), “uso antes do GC->uso depois do GC (tamanho do heap)” e o tempo de pausa - [dotnet-counters diagnostic tool](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/dotnet-counters) · .NET · A partir do .NET 9, aparece como dotnet.gc.pause.time; no .NET 8 e anteriores, como % Time in GC since last GC #### mem-swap · Swap · Swapping Quando falta memória e o SO manda parte dela para o disco, cada uso dessa memória passa a esperar pelo disco, que é mais de 1.000 vezes mais lento. - Por quê → Efeito → Na tela: A memória em uso passa da RAM física → O SO manda uma parte para o disco e lê de volta quando precisa → O tick dispara para centenas de ms, e todos os jogadores do servidor ficam em câmera lenta ou com travamento - Sintomas: Câmera lenta, Travamento / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Quanto mais tempo ligado, Horário de pico à noite - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Limitar o uso de memória do processo (tamanho do heap etc.) e procurar vazamentos. - O que fazer (Equipe de infraestrutura): Configurar os servidores do jogo para não usar swap, agir com base em alertas de memória e, como sem swap o processo é encerrado à força (OOM) no instante em que falta memória, garantir RAM com folga acima do uso de pico. - Números de referência: Leitura da RAM: cerca de 100 ns. Releitura do SSD: cerca de 100 µs (1.000 vezes). Disco na nuvem, do outro lado da rede: cerca de 1 ms (10 mil vezes). HDD: 10 ms (100 mil vezes). - No gráfico: Subida lenta (Uso de swap, swap in/out) - Onde olhar: Sobrepor ao tempo de tick as colunas si e so do vmstat 1 (quanto foi lido do swap e mandado para o swap por segundo), os valores some e full de /proc/pressure/memory (proporção de tempo parado esperando memória) e o majflt/s do pidstat -r no processo do servidor do jogo (page faults que exigiram leitura do disco) - Confirma se: No horário do lag, si fica acima de 0, e o majflt/s do servidor do jogo e o full de memory sobem juntos - Descarta se: si e so em 0 e pressão de memória (PSI) perto de 0: não é swap. Sem swap, mas com majflt/s e PSI subindo: a memória acabou e o SO está relendo páginas de código; liberar memória vem primeiro - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Servidores com GC leem o heap todo durante a coleta, então, mesmo que só uma parte do heap vá para o swap, um único GC pode passar a levar de alguns a dezenas de segundos. Sem swap, não existe a fase de lentidão causada pelo swap: o processo vai direto para o encerramento forçado (OOM), por isso é preciso garantir memória livre antes. Mesmo sem swap, quando a memória está quase no fim, o SO tira da memória até as páginas de código do executável e precisa lê-las de novo, e o servidor inteiro pode ficar muito lento por um tempo antes do encerramento forçado. - Fontes: - [Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · “Numbers Everyone Should Know”: referência à memória principal 100 ns, seek de disco 10 ms (dados de 2009) - [Documentation for /proc/sys/vm/](https://docs.kernel.org/admin-guide/sysctl/vm.html) · Linux kernel · swappiness: custo relativo entre swap e recuperação de páginas de arquivo; o swap é caro porque é I/O aleatório - [Concepts overview](https://docs.kernel.org/admin-guide/mm/concepts.html) · Linux kernel · O kernel recupera páginas do page cache que têm cópia no disco e páginas que podem ir para o swap; se ainda faltar memória, o OOM killer mata um processo - [Solidigm™ D7-P5520 and D7-P5620 Product Brief](https://www.solidigm.com/products/data-center/product-briefs/d7-p5520-p5620-product-brief.html) · Solidigm · Latência no percentil 99,99 (four-nines latency) de 130 µs em SSDs NVMe para servidores: base para dizer que uma leitura de SSD leva cerca de 100 µs - [Amazon EBS General Purpose SSD volumes](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html) · AWS · Latência de milissegundos de um dígito no disco padrão da nuvem (gp3) - [vmstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/vmstat.8.html) · procps-ng · si: memória lida do swap por segundo; so: memória mandada para o swap por segundo - [PSI - Pressure Stall Information](https://docs.kernel.org/accounting/psi.html) · Linux kernel · some (proporção de tempo em que algumas tarefas ficaram paradas) e full (proporção de tempo em que todas as tarefas ficaram paradas ao mesmo tempo) de /proc/pressure/memory - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -r: majflt/s (número de page faults que exigiram ler a página do disco) #### mem-cache-miss · Cache miss · CPU cache misses Quando os dados estão espalhados pela memória, a CPU precisa ir até a RAM, que é lenta, e esperar a cada acesso. - Por quê → Efeito → Na tela: Objetos ligados por ponteiros, espalhados pela memória e acessados sem ordem → Como os dados não estão no cache da CPU, cada leitura vai à RAM (cerca de 100 vezes mais lenta) → O mesmo trabalho custa várias vezes mais tempo de tick; nos casos graves, câmera lenta - Sintomas: Câmera lenta / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Sempre, Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Dispor em sequência na memória os dados usados juntos com frequência (design orientado a dados). - No gráfico: Sempre alto desde o início (Tempo de tick, uso de CPU) - Onde olhar: Rodar perf stat -d -p PID no processo do servidor do jogo para medir instruções por ciclo (insn per cycle) e cache misses de L1 e LLC, e comparar com o tempo de tick e o uso de CPU - Confirma se: A CPU fica ocupada o tempo todo, mas o insn per cycle é baixo e há muitos misses de LLC. Confirmado se um build com outra disposição dos dados reduz muito o tempo de tick com o mesmo número de jogadores - Descarta se: CPU com uso baixo, mas tick lento: causa que espera fora da CPU, como lock ou espera de I/O - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · 0,5 ns no cache L1, 7 ns no cache L2, 100 ns na memória principal (dados de 2009): ir até a RAM é uma ou duas ordens de grandeza mais lento que o cache - [perf-stat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-stat.1.html) · perf · -p conta os eventos de hardware de um processo em execução e mostra o insn per cycle; -d adiciona os eventos de cache de dados L1 e LLC #### mem-fragment · Fragmentação de memória · Heap fragmentation Quando alocações e liberações repetidas quebram o espaço livre em pedaços pequenos, o processo passa a ocupar muito mais memória do que realmente usa. - Por quê → Efeito → Na tela: Várias threads alocam e liberam, por muito tempo, blocos de memória de tamanhos variados → O espaço livre fica espalhado em pedaços pequenos que não podem ser devolvidos ao SO, e o uso cresce sem parar, como num vazamento → Quanto mais tempo ligado, mais lento por swap e falta de memória, até o encerramento forçado - Sintomas: Câmera lenta, Desconexão / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Quanto mais tempo ligado - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Pools de memória por tamanho, alocadores resistentes à fragmentação (jemalloc, mimalloc etc.). - No gráfico: Subida lenta (Memória do processo (RSS)) - Onde olhar: Subir dois servidores com o mesmo build e, em só um deles, reduzir o número de arenas da glibc com a variável de ambiente MALLOC_ARENA_MAX ou trocar para outro alocador, como o jemalloc; comparar o RSS do pidstat -r durante alguns dias - Confirma se: Com número parecido de jogadores e entidades, só no servidor alterado o RSS para de crescer ou cai bastante - Descarta se: Mesmo com outro alocador o RSS sobe igual: memória que não é liberada (mem-leak) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Como o problema se parece com um vazamento, a análise do heap não mostra nenhum ponto de vazamento. Com o alocador padrão do Linux (glibc), o problema é especialmente forte em servidores com muitas threads, e às vezes só trocar o alocador já reduz muito o uso de memória. - Fontes: - [mallopt(3) — Linux manual page](https://man7.org/linux/man-pages/man3/mallopt.3.html) · Linux man-pages · O malloc da glibc cria arenas até um múltiplo do número de CPUs para reduzir a contenção entre threads, e quanto mais arenas, maior o uso de memória (limite com M_ARENA_MAX, também configurável pela variável de ambiente MALLOC_ARENA_MAX) - [jemalloc memory allocator](https://jemalloc.net/) · jemalloc · Implementação de malloc de uso geral focada em evitar fragmentação e escalar com concorrência - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -r: RSS por processo (memória realmente carregada na RAM) #### mem-numa · Acesso a memória NUMA remota · Remote NUMA access Em servidores com duas CPUs, usar a memória ligada à outra CPU deixa o acesso mais lento. - Por quê → Efeito → Na tela: A thread e a memória ficam em sockets de CPU diferentes → O acesso à memória fica mais lento (1,5–2 vezes, conforme o hardware) → Mesma configuração de hardware, mas desempenho diferente em cada processo - Sintomas: Câmera lenta / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Sempre - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Fixar processo e memória em um socket (numactl), separar os processos do servidor do jogo por socket quando houver dois sockets. - No gráfico: Alto só em alguns (Tempo de tick por processo, memória por nó) - Onde olhar: Com numastat -p PID, ver em que nó NUMA está a memória do processo do servidor do jogo e se numa_miss e other_node do numastat estão crescendo; comparar com o nó da CPU em que o processo roda - Confirma se: Só nos processos lentos a maior parte da memória fica em um nó diferente da CPU em que rodam, e a diferença some ao reiniciá-los com CPU e memória fixadas em um só nó via numactl - Descarta se: Lento mesmo com a mesma distribuição de nós dos processos rápidos: outra causa, como noisy neighbor, throttling de CPU ou carga daquele processo - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [What is NUMA?](https://docs.kernel.org/mm/numa.html) · Linux kernel · A memória da mesma célula é mais rápida e tem mais largura de banda; a memória de outra célula (remota) tem acesso mais lento - [numactl(8) — Linux manual page](https://man7.org/linux/man-pages/man8/numactl.8.html) · numactl · --cpunodebind e --membind fixam a CPU e a memória do processo em um nó NUMA específico - [numastat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/numastat.8.html) · numactl · Contadores numa_miss (alocação fora do nó desejado) e other_node (alocação neste nó por um processo rodando em outro nó); -p mostra a memória do processo por nó ### L11 Disco (9 causas) #### dk-sync-log · Escrita síncrona de logs · Synchronous logging Se a thread do jogo espera o disco confirmar cada linha de log, o jogo também para quando o disco está ocupado. - Por quê → Efeito → Na tela: A thread do jogo grava os logs de combate e de trocas direto em arquivo → Quando se exige gravação garantida (fsync) ou o buffer de escrita do SO (page cache) chega ao limite, uma única escrita leva dezenas de ms se o disco estiver ocupado → Engasgos em combates que geram muito log - Sintomas: Engasgos, Travamento / Fatores: Paralisação - Quem: Local ou canal específico, Servidor inteiro / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Usar logging assíncrono (buffer em memória + thread separada), reduzir o volume de logs, não chamar fsync na thread do jogo. - O que fazer (Equipe de infraestrutura): Rodar a rotação e a compressão de logs com prioridade de I/O baixa, colocar os logs em um disco separado dos dados, monitorar a latência de escrita do disco. - No gráfico: Picos aleatórios (Tempo de tick do servidor, latência de escrita do disco) - Onde olhar: Sobrepor w_await e aqu-sz do iostat -x 1 ao tempo de tick e, com perf trace -p PID --duration 10, encontrar no servidor do jogo as chamadas write e fsync que levaram mais de 10 ms e as threads que as fizeram - Confirma se: No horário do pico de tick, chamadas write ou fsync da thread do jogo levam dezenas de ms, e a latência de escrita do disco dispara no mesmo instante. Muitas vezes coincide com o horário de rotação ou compressão de logs - Descarta se: Picos de tick sem chamadas de sistema demoradas na thread do jogo: outra causa, como GC, lock ou estouro do tick. Só a thread dedicada a logs demora: o jogo não é afetado - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Normalmente o SO recebe a escrita primeiro na memória (page cache) e só depois a grava no disco, então uma linha de log costuma terminar na hora. A pausa acontece quando o fsync exige gravação garantida, quando as escritas pendentes passam do limite e o SO bloqueia a chamada de escrita, ou quando o arquivo de log é rotacionado ou comprimido. Por isso tudo fica normal no dia a dia, e os picos só aparecem nos momentos em que o disco está ocupado. - Fontes: - [fsync(2) — Linux manual page](https://man7.org/linux/man-pages/man2/fsync.2.html) · Linux man-pages · O fsync grava os dados alterados no disco (incluindo o cache do disco) e bloqueia até o dispositivo confirmar a conclusão - [Documentation for /proc/sys/vm/](https://docs.kernel.org/admin-guide/sysctl/vm.html) · Linux kernel · Quando as escritas pendentes (dirty) chegam ao dirty_ratio, o próprio processo que escreve passa a fazer a gravação no disco - [ionice(1) — Linux manual page](https://man7.org/linux/man-pages/man1/ionice.1.html) · util-linux · Tarefas com prioridade de I/O idle só recebem tempo de disco quando nenhum outro programa está usando o disco - [iostat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/iostat.1.html) · sysstat · -x: w_await (tempo médio de atendimento das requisições de escrita, incluindo a espera na fila), aqu-sz (tamanho médio da fila, antigo avgqu-sz) - [perf-trace(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-trace.1.html) · perf · -p rastreia as chamadas de sistema de um processo em execução; --duration mostra só as chamadas que levaram mais que os ms indicados #### dk-fsync · Tempestade de fsync · fsync storms Pedir que os dados sejam gravados “de verdade” no disco leva de 0,1 ms a dezenas de ms por chamada, conforme o disco, e, quando os pedidos se acumulam, a fila cresce. - Por quê → Efeito → Na tela: Salvamentos periódicos e ondas de logout concentram pedidos de gravação garantida → A fila do disco cresce → Lag a cada salvamento, atraso no logout e na troca de canal - Sintomas: Engasgos, Input lag / Fatores: Paralisação, Latência - Quem: Servidor inteiro / Quando: Em intervalos regulares, Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Agrupar salvamentos e gravar de uma vez (vários salvamentos com um só fsync), espalhar os horários de salvamento. - O que fazer (Equipe de infraestrutura): Servidores/SO: usar SSD para servidores com proteção contra queda de energia, monitorar o tamanho da fila do disco e a latência do fsync. Servidores de BD: se os salvamentos vão para o BD, colocar também o disco de log do BD no mesmo tipo de SSD, monitorar a latência de commit. - Números de referência: O tempo por chamada varia conforme o hardware, mas fica mais ou menos em 0,1 ms em SSD para servidores (com proteção contra queda de energia), de 1 a alguns ms em SSD comum, 1–2 ms em disco na nuvem e 10 ms ou mais em HDD. Se uma thread espera uma chamada de cada vez, o HDD não consegue fazer nem 100 em 1 segundo. - No gráfico: Picos em intervalos regulares (Tamanho da fila do disco, latência de flush e de escrita) - Onde olhar: Sobrepor aos horários de salvamento periódico e de logout o f/s e o f_await do iostat -x 1 (número de flushes atendidos pelo disco e tempo gasto), além de w/s, aqu-sz e w_await. Versões antigas do sysstat mostram aqu-sz como avgqu-sz. Em disco na nuvem, ver VolumeQueueLength e VolumeAvgWriteLatency do EBS - Confirma se: A cada salvamento e onda de logouts, o número de flushes e o tamanho da fila disparam juntos, e w_await e f_await ficam várias vezes acima do normal. Nesses momentos, o salvamento e a troca de canal atrasam - Descarta se: A fila dispara em horários sem relação com salvamentos e logouts: backup e compressão (dk-backup) ou limite de IOPS (dk-iops). Número de flushes igual, mas tudo mais lento: mais provável, esgotamento dos créditos de burst (dk-burst) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [fsync(2) — Linux manual page](https://man7.org/linux/man-pages/man2/fsync.2.html) · Linux man-pages · O fsync esvazia até o cache do disco e bloqueia até o dispositivo confirmar a conclusão - [Reliability (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/wal-reliability.html) · PostgreSQL · Discos SATA comuns e muitos SSDs têm cache de escrita que se perde numa queda de energia; para gravação garantida, é preciso cache com bateria ou proteção contra queda de energia - [Amazon EBS General Purpose SSD volumes](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html) · AWS · Latência de milissegundos de um dígito no disco padrão da nuvem (gp3); no io2 Block Express, média abaixo de 500 µs para I/O de 16 KiB - [Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Um seek de HDD: 10 ms - [iostat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/iostat.1.html) · sysstat · -x: f/s e f_await (número de requisições de flush atendidas pelo disco e tempo médio), w/s, w_await, aqu-sz (antigo avgqu-sz) - [Amazon CloudWatch metrics for Amazon EBS](https://docs.aws.amazon.com/ebs/latest/userguide/using_cloudwatch_ebs.html) · AWS · VolumeQueueLength (requisições esperando conclusão), VolumeAvgWriteLatency (latência média de escrita em 1 minuto, instâncias Nitro) #### dk-burst · Esgotamento dos créditos de burst do disco na nuvem · Burst credit depletion Alguns discos na nuvem e instâncias pequenas têm créditos de burst, que permitem passar do desempenho base por um tempo; quando o período de uso intenso se prolonga e os créditos acabam, a velocidade cai de repente. - Por quê → Efeito → Na tela: Uso acima do desempenho base por muito tempo → Os créditos de burst acabam e o desempenho despenca para o nível base → O lag começa toda noite, depois de algumas horas de pico - Sintomas: Engasgos, Câmera lenta, Input lag / Fatores: Paralisação, Latência - Quem: Servidor inteiro / Quando: Horário de pico à noite, Quanto mais tempo ligado - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Servidores/SO: usar discos com desempenho garantido (gp3, IOPS provisionados), criar alerta de saldo de créditos, verificar também o limite de burst da largura de banda de disco da instância e os créditos de CPU. Servidores de BD: trocar também os discos do BD, incluindo BD gerenciado, por discos com desempenho garantido e criar alerta de saldo de créditos. - Números de referência: Um disco gp2 de 100 GB na AWS entrega 300 IOPS normalmente e 3.000 IOPS em burst e, com os créditos cheios, aguenta cerca de 30 minutos. O gp3 não usa créditos e entrega sempre 3.000. Os Premium SSD pequenos do Azure também fazem burst por até 30 minutos com créditos. - No gráfico: Achata ao bater no limite (IOPS, saldo de créditos de burst) - Onde olhar: Ver no CloudWatch o BurstBalance do EBS (gp2, st1, sc1), o EBSIOBalance% e o EBSByteBalance% da instância (algumas instâncias com burst) e o CPUCreditBalance das instâncias burstable. No Azure, ver métricas de uso de créditos de burst, como Data Disk Used Burst IO Credits Percentage - Confirma se: A partir do momento em que o saldo cai para perto de 0, o IOPS (VolumeReadOps, VolumeWriteOps) achata no desempenho base, e VolumeQueueLength e o lag aumentam juntos. Começa depois de algumas horas seguidas de pico - Descarta se: Saldos todos folgados, mas IOPS achatado: limite fixo do volume ou da instância (dk-iops) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Mesmo com o disco em ordem, máquinas virtuais pequenas têm limite de burst na própria largura de banda de disco da instância (por exemplo, pelo menos 30 minutos por dia), e o gráfico fica com o mesmo formato. Servidores baratos que usam créditos de CPU também caem para o desempenho base quando os créditos acabam. - Fontes: - [Amazon EBS General Purpose SSD volumes](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html) · AWS · Desempenho base do gp2 de 3 IOPS por GiB (mínimo de 100), burst até 3.000 IOPS com créditos de I/O, 5,4 milhões de créditos garantem pelo menos 30 minutos. O gp3 não tem burst e entrega sempre 3.000 IOPS - [Managed disk bursting](https://learn.microsoft.com/en-us/azure/virtual-machines/disk-bursting) · Microsoft Azure · Premium SSD P20 ou menor tem burst baseado em créditos; com os créditos cheios, 30 minutos na velocidade máxima de burst - [Amazon EBS-optimized instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-optimized.html) · AWS · Algumas instâncias só mantêm o desempenho máximo de EBS por 30 minutos a cada 24 horas e depois voltam ao desempenho base - [Standard mode for burstable performance instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-performance-instances-standard-mode.html) · AWS · No modo padrão, instâncias burstable sem créditos de CPU reduzem o uso de CPU ao nível base (aos poucos, sem queda brusca) - [Amazon CloudWatch metrics for Amazon EBS](https://docs.aws.amazon.com/ebs/latest/userguide/using_cloudwatch_ebs.html) · AWS · BurstBalance: saldo (%) de créditos de I/O do gp2 e de créditos de vazão do st1 e sc1; VolumeReadOps, VolumeWriteOps, VolumeQueueLength - [CloudWatch metrics that are available for your instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) · AWS · EBSIOBalance% e EBSByteBalance%: saldo de créditos de EBS de algumas instâncias que fazem burst de 30 minutos a cada 24 horas; CPUCreditBalance: saldo de créditos de CPU das instâncias burstable - [Disk metrics](https://learn.microsoft.com/en-us/azure/virtual-machines/disks-metrics) · Microsoft Azure · Uso de créditos de burst de disco e de VM, como Data Disk Used Burst IO Credits Percentage (intervalos de 5 minutos) #### dk-iops · Limite de IOPS e saturação da fila · IOPS limit / queue saturation Quando as requisições passam do que o disco consegue atender em 1 segundo, a fila cresce e a latência dispara. - Por quê → Efeito → Na tela: As requisições de leitura e escrita chegam perto da capacidade do disco → A fila cresce (em geral, dispara a partir de 90% de utilização) → Atraso em salvamentos e carregamentos; travamento se a chamada for síncrona - Sintomas: Input lag, Travamento / Fatores: Latência, Paralisação - Quem: Servidor inteiro / Quando: Quando junta muita gente, Horário de pico à noite - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Agrupar requisições, manter em cache os dados lidos com frequência, usar I/O assíncrono para a thread do jogo não esperar o disco. - O que fazer (Equipe de infraestrutura): Servidores/SO: usar discos mais rápidos, verificar os limites de largura de banda de disco e de IOPS de cada tipo de instância, criar alertas de utilização e fila do disco, fazer cópias de arquivos grandes em horários tranquilos. Servidores de BD: criar alertas de utilização de IOPS e vazão também nos discos do BD, verificar os limites de disco da configuração da instância do BD. - Números de referência: HDD: cerca de 150 IOPS; SSD SATA: dezenas de milhares; NVMe: centenas de milhares. O disco padrão da nuvem (AWS gp3) entrega 3.000 IOPS e 125 MiB por segundo; o limite de vazão por segundo é separado do de IOPS, e se uma cópia de arquivo grande o esgota, até escritas pequenas ficam esperando na fila. - No gráfico: Achata ao bater no limite (IOPS, tamanho da fila do disco) - Onde olhar: Ver r/s e w/s, rkB/s e wkB/s, aqu-sz, r_await e w_await no iostat -x 1. Na nuvem, ver VolumeReadOps, VolumeWriteOps e VolumeQueueLength do EBS e, para saber se o limite foi excedido, VolumeIOPSExceededCheck e VolumeThroughputExceededCheck, além de InstanceEBSIOPSExceededCheck e InstanceEBSThroughputExceededCheck do lado da instância - Confirma se: As requisições por segundo ou a vazão achatam no valor do limite, e aqu-sz e await disparam juntos. Na nuvem, as métricas de limite excedido ficam em 1 - Descarta se: %util em 100% com await baixo: ainda pode haver folga. Em SSD e RAID, que atendem requisições em paralelo, %util não indica o limite. await alto sem bater no limite: latência do próprio disco (dk-hdd) ou fsync (dk-fsync) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Na nuvem, além do limite do disco, cada configuração de servidor (tipo de instância) tem limites próprios de largura de banda de disco e de IOPS. Mesmo com um disco caro, se o servidor for pequeno, o gargalo fica no limite da instância. - Fontes: - [Exos X18 Data Sheet](https://www.seagate.com/www-content/datasheets/pdfs/exos-x18-mango-DS2045-1N-2007US-en_US.pdf) · Seagate · HDD de 7.200 rpm para servidores: 170 IOPS em leitura aleatória de 4K (QD16) - [D3-S4520 SSD](https://www.solidigm.com/products/data-center/d3/s4520.html) · Solidigm · SSD SATA para servidores: até 92K/48K IOPS em leitura/escrita aleatória de 4 KB - [Solidigm™ D7-P5520 and D7-P5620 Product Brief](https://www.solidigm.com/products/data-center/product-briefs/d7-p5520-p5620-product-brief.html) · Solidigm · SSD NVMe para servidores: 1.000K/200K IOPS em leitura/escrita aleatória - [Amazon EBS General Purpose SSD volumes](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html) · AWS · Desempenho base do gp3 de 3.000 IOPS e 125 MiB/s, dois limites separados que podem ser aumentados de forma independente - [Amazon EBS-optimized instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-optimized.html) · AWS · Cada tipo de instância tem limites próprios, base e máximo, de largura de banda, vazão e IOPS de EBS - [iostat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/iostat.1.html) · sysstat · -x: r/s e w/s, rkB/s e wkB/s, aqu-sz (antigo avgqu-sz), r_await e w_await, %util. Em RAID e SSDs modernos, que atendem requisições em paralelo, %util não indica o limite de desempenho - [Amazon CloudWatch metrics for Amazon EBS](https://docs.aws.amazon.com/ebs/latest/userguide/using_cloudwatch_ebs.html) · AWS · VolumeIOPSExceededCheck e VolumeThroughputExceededCheck: 1 se houve tentativa de passar do limite de IOPS ou de vazão do volume (instâncias Nitro); VolumeQueueLength - [CloudWatch metrics that are available for your instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) · AWS · InstanceEBSIOPSExceededCheck e InstanceEBSThroughputExceededCheck: 1 se houve tentativa de passar do limite de IOPS ou de vazão de EBS da instância #### dk-full · Disco cheio · Disk full Quando logs e dumps se acumulam e o disco enche, as escritas falham e, se o código não estiver preparado para isso, o servidor cai. - Por quê → Efeito → Na tela: Logs, dumps e arquivos temporários se acumulam até 100% → A escrita falha. Sem tratamento de erro, crash; com tratamento, falha ao salvar → Desconexão, rollback do progresso - Sintomas: Desconexão, Ação perdida / rollback / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Quanto mais tempo ligado - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Tratar falhas de escrita com nova tentativa de salvamento e alerta (sem deixar o processo cair), reduzir logs e dumps desnecessários. - O que fazer (Equipe de infraestrutura): Servidores/SO: fazer rotação de logs, criar alerta de espaço em disco, separar os discos de logs e de dados. Servidores de BD: monitorar se o log de transações do BD (WAL, binlog) está acumulando por replicação parada ou backup de log que não rodou. - No gráfico: Subida lenta (Uso do disco) - Onde olhar: Ver o uso no df -h e o uso de inodes no df -i, e procurar erros ENOSPC nos logs do servidor e do BD. No BD, ver slots com active em false no pg_replication_slots do PostgreSQL, o número e o tamanho dos arquivos no SHOW BINARY LOGS do MySQL, o log_reuse_wait_desc no sys.databases do SQL Server e, no RDS, o FreeStorageSpace - Confirma se: O uso sobe de forma constante ao longo de vários dias, o momento em que chega a 100% coincide com o crash ou com as falhas de salvamento, e o log registra ENOSPC - Descarta se: Espaço de sobra, mas a escrita falha: outra causa, como permissão ou limite de tamanho de arquivo - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O log de transações do BD (WAL, binlog etc.) não é apagado e continua crescendo se uma réplica para ou se um backup de log deixa de rodar. Quando esse disco enche, todas as escritas do BD param, e salvamentos e trocas falham todos de uma vez. - Fontes: - [write(2) — Linux manual page](https://man7.org/linux/man-pages/man2/write.2.html) · Linux man-pages · Sem espaço no dispositivo, a escrita falha com o erro ENOSPC - [Monitoring Disk Usage (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/diskusage.html) · PostgreSQL · Se o disco do WAL enche, o servidor do BD pode encerrar com panic - [Log-Shipping Standby Servers (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/warm-standby.html) · PostgreSQL · O slot de replicação não apaga o WAL até a réplica recebê-lo e pode encher o espaço do pg_wal (limite com max_slot_wal_keep_size) - [Troubleshoot a full transaction log (SQL Server Error 9002)](https://learn.microsoft.com/en-us/sql/relational-databases/logs/troubleshoot-a-full-transaction-log-sql-server-error-9002) · Microsoft SQL Server · Com o log cheio, o BD só aceita leitura e não permite alterações; backup de log que não rodou, atraso de replicação e transações longas são causas comuns que impedem a limpeza do log, e o que está bloqueando aparece em log_reuse_wait_desc no sys.databases - [df(1) — Linux manual page](https://man7.org/linux/man-pages/man1/df.1.html) · coreutils · Uso por sistema de arquivos; -i: uso de inodes (o padrão mostra blocos) - [pg_replication_slots (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/view-pg-replication-slots.html) · PostgreSQL · active: se o slot está transmitindo (streaming) agora; wal_status: se o WAL retido pelo slot passou de max_wal_size - [SHOW BINARY LOGS Statement](https://dev.mysql.com/doc/refman/8.4/en/show-binary-logs.html) · MySQL · Lista dos arquivos de log binário do servidor e tamanho de cada arquivo (File_size) - [Amazon CloudWatch metrics for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-metrics.html) · AWS · FreeStorageSpace: espaço de armazenamento livre na instância do BD #### dk-backup · Backup, compressão e varreduras · Backup / compression / scans Quando backups de madrugada, compressão de logs e varreduras de segurança monopolizam o disco, as leituras e escritas do servidor do jogo ficam na fila. - Por quê → Efeito → Na tela: Começa um job agendado de backup ou compressão → O job ocupa a maior parte da largura de banda e do IOPS do disco → Lag todo dia no mesmo horário - Sintomas: Engasgos, Input lag / Fatores: Paralisação, Latência - Quem: Servidor inteiro / Quando: Em intervalos regulares - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Servidores/SO: baixar a prioridade de I/O dos jobs de backup, compressão e varredura, espalhar os horários. Servidores de BD: fazer o backup a partir de uma réplica. - No gráfico: Picos em intervalos regulares (Utilização do disco, tempo de espera do disco) - Onde olhar: Com sar -d, sobrepor por data o %util, o await e o aqu-sz dos últimos dias (arquivos diários em /var/log/sa; o sadc precisa coletar também os dados de disco com -S DISK) e, nesse horário, achar com pidstat -d 1 o processo com maior kB_rd/s e kB_wr/s e comparar com a agenda do cron e dos timers do systemd - Confirma se: Todo dia no mesmo horário, await e %util disparam, e nesse momento um processo de backup, compressão ou varredura responde pela maior parte das leituras e escritas do disco - Descarta se: Picos em horários diferentes a cada dia: pouco provável que seja job agendado. Nesse horário, a maior parte do I/O é do próprio servidor do jogo: salvamentos e logs (dk-fsync, dk-sync-log) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [ionice(1) — Linux manual page](https://man7.org/linux/man-pages/man1/ionice.1.html) · util-linux · Tarefas na classe idle só recebem tempo de disco quando nenhum outro programa está usando o disco - [Using Replication for Backups](https://dev.mysql.com/doc/refman/8.4/en/replication-solutions-backups.html) · MySQL · Parar uma réplica para fazer backup não afeta a operação do BD primário - [sar(1) — Linux manual page](https://man7.org/linux/man-pages/man1/sar.1.html) · sysstat · -d: await, aqu-sz e %util por dispositivo nos arquivos diários (padrão /var/log/sa); os dados de disco precisam ser coletados com a opção -S DISK do sadc - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -d: kB_rd/s e kB_wr/s por processo (volume lido e gravado no disco por segundo) #### dk-lazy-load · Lazy loading no servidor · Lazy loading on the server Se o servidor lê do disco os dados de uma dungeon ou de um mapa só quando alguém pede pela primeira vez, todos ficam parados durante aquele tick. - Por quê → Efeito → Na tela: Alguém entra pela primeira vez em uma dungeon ou área → O servidor lê os dados do disco na thread do jogo → Um breve travamento para todos naquele servidor - Sintomas: Travamento / Fatores: Paralisação - Quem: Local ou canal específico, Servidor inteiro / Quando: Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Carregar tudo antecipadamente na inicialização do servidor, carregamento assíncrono. - O que fazer (Equipe de infraestrutura): Em servidores recém-criados a partir de snapshot, aquecer o disco antes de colocá-los em produção (ler todos os blocos uma vez) ou usar o recurso de restauração rápida de snapshot. - No gráfico: Picos aleatórios (Tempo de tick do servidor, leituras de disco) - Onde olhar: Cruzar o horário da parada com os registros de primeira entrada em dungeons e áreas no log do servidor do jogo e, nesse instante, ver as leituras de disco do servidor do jogo (kB_rd/s no pidstat -d) e as chamadas read e open demoradas com perf trace --duration. Em servidor na nuvem recém-criado, comparar o VolumeAvgReadLatency do EBS com o de um servidor antigo - Confirma se: Para só no momento da primeira entrada e não para quando alguém entra no mesmo lugar pela segunda vez. Durante a parada, a thread do jogo está esperando leitura de arquivo - Descarta se: Para do mesmo jeito em áreas já carregadas: outra causa, como estouro do tick ou GC - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Na nuvem, um servidor recém-criado a partir de snapshot (cópia do disco) busca no storage remoto cada bloco lido pela primeira vez e fica bem mais lento que o normal. Se a primeira entrada só demora muito nos servidores que o autoscaling acabou de subir, suspeite disso. - Fontes: - [Initialize Amazon EBS volumes](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-initialize.html) · AWS · Volumes criados a partir de snapshot têm latência maior e desempenho menor enquanto os blocos são buscados do S3; inicializar antes lendo todos os blocos com dd ou fio - [Amazon EBS fast snapshot restore](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-fast-snapshot-restore.html) · AWS · A restauração rápida de snapshot entrega volumes já inicializados desde a criação, eliminando a latência do primeiro acesso - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · -d: kB_rd/s por processo (volume lido do disco por segundo) - [perf-trace(1) — Linux manual page](https://man7.org/linux/man-pages/man1/perf-trace.1.html) · perf · Mostra só as chamadas de sistema que levaram mais que os ms indicados em --duration - [Amazon CloudWatch metrics for Amazon EBS](https://docs.aws.amazon.com/ebs/latest/userguide/using_cloudwatch_ebs.html) · AWS · VolumeAvgReadLatency: latência média de leitura em 1 minuto (instâncias Nitro) #### dk-coredump · Gravação de core dump · Core dump writing Quando o servidor cai, gravar no disco vários GB de memória pode atrasar o reinício em vários minutos. - Por quê → Efeito → Na tela: Com o crash do servidor, a memória inteira é gravada em arquivo → Não dá para reiniciar enquanto vários GB são gravados → Depois da queda do servidor e da desconexão, o jogo não conecta por um bom tempo - Sintomas: Não conecta / loading infinito / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Avaliar dumps pequenos, só com a memória necessária (minidump), corrigir a causa do crash. - O que fazer (Equipe de infraestrutura): Limitar o tamanho do dump (configuração de core dump do SO), usar disco rápido, separar o reinício do dump (comprimir e enviar o dump à parte, depois do reinício). - No gráfico: Queda de conexões em massa (Número de conexões, horário de reinício do servidor) - Onde olhar: Colocar lado a lado o horário do crash, o tamanho do arquivo core (coredumpctl list e info, ou o arquivo no local indicado por core_pattern), o horário em que o arquivo terminou de ser gravado e o horário em que o serviço voltou, e ver o wkB/s do iostat -x nesse intervalo - Confirma se: Depois do crash, a escrita em disco fica perto do limite enquanto o arquivo core de vários GB é gravado, e o reinício só começa quando a gravação termina - Descarta se: Core dump desligado ou pequeno, mas o reinício demora: etapa de inicialização do servidor, como carregamento de mapas ou cache frio do BD (db-cold-cache) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [core(5) — Linux manual page](https://man7.org/linux/man-pages/man5/core.5.html) · Linux man-pages · RLIMIT_CORE limita o tamanho do arquivo core, coredump_filter escolhe as áreas de memória incluídas, e o core dump pode ser enviado por pipe a um programa e processado à parte - [Minidump Files](https://learn.microsoft.com/en-us/windows/win32/debug/minidump-files) · Microsoft · O minidump guarda só a parte útil das informações do crash dump, para ser rápido e pequeno - [coredumpctl(1) — Linux manual page](https://man7.org/linux/man-pages/man1/coredumpctl.1.html) · systemd · list: lista dos core dumps registrados no journal (TIME é o horário do crash informado pelo kernel); info: detalhes de cada dump e tamanho gravado no disco - [iostat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/iostat.1.html) · sysstat · -x: wkB/s (volume gravado no disco por segundo) #### dk-hdd · Latência de seek do HDD · HDD seek latency No HDD, a cabeça de leitura precisa se mover sobre o prato (seek), então cada leitura ou escrita de dados espalhados leva perto de 10 ms. - Por quê → Efeito → Na tela: HDD em servidores antigos ou storage barato → Cerca de 10 ms por leitura ou escrita espalhada → Atraso geral em salvamentos e carregamentos - Sintomas: Input lag / Fatores: Latência - Quem: Servidor inteiro / Quando: Sempre - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Projetar priorizando escritas sequenciais. - O que fazer (Equipe de infraestrutura): Servidores/SO: trocar por SSD (começando pelos discos de armazenamento com muitas leituras e escritas aleatórias). Servidores de BD: trocar primeiro por SSD os discos do BD com mais leituras e escritas aleatórias. - No gráfico: Sempre alto desde o início (Latência de leitura e escrita do disco (r_await, w_await)) - Onde olhar: Verificar com lsblk -d -o NAME,ROTA se é disco rotativo (HDD) e ver r/s e w/s, r_await e w_await no iostat -x 1. Em máquina virtual, verificar o tipo de disco na especificação da nuvem ou do storage - Confirma se: Disco rotativo, e r_await e w_await sempre entre alguns ms e dezenas de ms, mesmo com só dezenas a pouco mais de cem requisições por segundo - Descarta se: SSD com latência alta: mais provável, fila saturada (dk-iops) ou créditos de burst esgotados (dk-burst) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Um seek de disco 10 ms, leitura sequencial de 1 MB do disco 20 ms - [Exos X18 Data Sheet](https://www.seagate.com/www-content/datasheets/pdfs/exos-x18-mango-DS2045-1N-2007US-en_US.pdf) · Seagate · HDD de 7.200 rpm: latência rotacional média de 4,16 ms, 170 IOPS em leitura aleatória de 4K - [lsblk(8) — Linux manual page](https://man7.org/linux/man-pages/man8/lsblk.8.html) · util-linux · -o escolhe as colunas de saída; as colunas de topologia do dispositivo incluem ROTA (se é rotativo) - [ABI stable symbols](https://docs.kernel.org/admin-guide/abi-stable.html) · Linux kernel · /sys/block/(disco)/queue/rotational: indica se o dispositivo é rotativo ou não rotativo - [iostat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/iostat.1.html) · sysstat · -x: r/s e w/s, r_await e w_await (tempo médio de atendimento por requisição, incluindo a espera na fila) ### L12 Banco de dados (16 causas) #### db-no-index · Query sem índice · Missing index / full table scan Sem índice, para achar as linhas que atendem à condição é preciso ler a tabela inteira (full scan). - Por quê → Efeito → Na tela: O deploy de um recurso novo adiciona uma busca por uma condição sem índice → Milhões de linhas são varridas, e uma única query leva de centenas de ms a alguns segundos → Atraso para carregar a caixa de correio e o histórico de trocas; as conexões ficam presas e outras requisições também esperam - Sintomas: Input lag, Não conecta / loading infinito / Fatores: Latência, Paralisação - Quem: Só um recurso específico, Servidor inteiro / Quando: Ao fazer ações específicas - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Revisar o plano de execução das queries novas antes do deploy, adicionar índices, verificar se as queries que alteram dados (UPDATE, DELETE) também usam índice. - O que fazer (Equipe de infraestrutura): Monitorar o log de queries lentas, encontrar as queries com full scan e compartilhar com a equipe de desenvolvimento, criar índices em produção pelo método online, que segura lock por pouco tempo. - Números de referência: Com índice, alguns ms; sem índice, a query fica mais lenta em proporção ao volume de dados e, em tabelas grandes, chega a ser de centenas a dezenas de milhares de vezes mais lenta. - No gráfico: Degrau a partir de um momento (Latência das queries do BD, linhas lidas) - Onde olhar: No MySQL, ver Rows_examined e Rows_sent no slow query log (com log_queries_not_using_indexes ativado, ele também registra queries que não usam índice) e SUM_NO_INDEX_USED e SUM_ROWS_EXAMINED em events_statements_summary_by_digest do performance_schema, e rodar EXPLAIN. No PostgreSQL, ver seq_scan e seq_tup_read em pg_stat_user_tables e rodar EXPLAIN - Confirma se: Uma query que apareceu depois do deploy lê milhares de vezes mais linhas (Rows_examined) do que retorna (Rows_sent), e o EXPLAIN mostra varredura da tabela inteira (MySQL type ALL, PostgreSQL Seq Scan). O seq_tup_read de uma tabela grande cresce rápido a partir do horário do deploy - Descarta se: Usa índice e mesmo assim está lenta: espera por lock (db-hot-row, db-ddl-lock) ou mudança no plano de execução (db-plan-flip). Full scan em tabela pequena pode ser normal - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Não são só as leituras que ficam lentas. Dependendo do BD, queries que alteram dados sem índice (UPDATE, DELETE) põem lock até nas linhas varridas e podem bloquear o salvamento de jogadores que não têm nada a ver com elas. - Fontes: - [How MySQL Uses Indexes](https://dev.mysql.com/doc/refman/8.4/en/mysql-indexes.html) · MySQL · Sem índice, o banco lê a tabela inteira a partir da primeira linha, e quanto maior a tabela, maior o custo - [Locks Set by Different SQL Statements in InnoDB](https://dev.mysql.com/doc/refman/8.4/en/innodb-locks-set.html) · MySQL · Se não houver índice adequado e a tabela inteira for varrida, todas as linhas recebem lock e até inserções de outros usuários ficam bloqueadas - [The Slow Query Log](https://dev.mysql.com/doc/refman/8.4/en/slow-query-log.html) · MySQL · Registra as queries que passam do long_query_time (padrão de 10 segundos); também é possível registrar à parte as queries que não usam índice - [CREATE INDEX (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/sql-createindex.html) · PostgreSQL · Com CONCURRENTLY, o índice é criado sem bloquear escritas; a criação normal bloqueia escritas até terminar - [Statement Summary Tables](https://dev.mysql.com/doc/refman/8.4/en/performance-schema-statement-summary-tables.html) · MySQL · events_statements_summary_by_digest: por formato de query, SUM_NO_INDEX_USED (vezes em que rodou sem índice) e SUM_ROWS_EXAMINED - [EXPLAIN Output Format](https://dev.mysql.com/doc/refman/8.4/en/explain-output.html) · MySQL · type ALL indica varredura da tabela inteira, que em geral se evita adicionando um índice - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · seq_scan (número de varreduras sequenciais) e seq_tup_read (linhas lidas por varredura sequencial) em pg_stat_user_tables - [Using EXPLAIN (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/using-explain.html) · PostgreSQL · Seq Scan: plano de execução que lê todas as linhas da tabela em ordem #### db-hot-row · Contenção de lock em hot row · Hot row lock contention Quando todos tentam alterar a mesma linha (baú da guilda, item popular na casa de leilões, contador global do servidor), só um de cada vez consegue o lock. - Por quê → Efeito → Na tela: Eventos e itens populares concentram as alterações na mesma linha → As requisições esperam até conseguir o lock → Trocas falham, “tente novamente mais tarde”, timeouts - Sintomas: Ação perdida / rollback, Input lag / Fatores: Paralisação, Latência - Quem: Só um recurso específico / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Dividir a linha (contadores com sharding), manter as transações curtas, acumular em memória e gravar de uma vez. - O que fazer (Equipe de infraestrutura): Monitorar o tempo e o número de esperas por lock de linha, encontrar as linhas onde a contenção se concentra e compartilhar. - Números de referência: Se cada requisição segura o lock por 10 ms, aquela linha só pode ser alterada no máximo 100 vezes por segundo. Se a transação incluir uma ida e volta a outro servidor, esse número cai ainda mais. - No gráfico: Sobe com a carga (Número e tempo de esperas por lock de linha) - Onde olhar: No MySQL, ver o aumento de Innodb_row_lock_waits e Innodb_row_lock_time e o Innodb_row_lock_current_waits, e descobrir quem espera por quem com sys.innodb_lock_waits. No PostgreSQL, ver as sessões com wait_event_type igual a Lock no pg_stat_activity e as requisições com granted em false no pg_locks; com log_lock_waits ativado (desligado por padrão), as esperas longas por lock ficam no log - Confirma se: As esperas por lock crescem rápido acompanhando o evento e o número de jogadores, e a maioria das requisições em espera aponta para a mesma linha (mesma chave) da mesma tabela - Descarta se: Esperas espalhadas de forma uniforme por várias tabelas e linhas: mais provável, saturação de disco ou CPU. Uma sessão segura o lock por muito tempo e não solta: transação aberta por muito tempo (db-long-tx) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [InnoDB Locking](https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html) · MySQL · Quando uma transação põe lock em uma linha (registro do índice), as outras transações não conseguem alterar essa linha e esperam - [How to Minimize and Handle Deadlocks](https://dev.mysql.com/doc/refman/8.4/en/innodb-deadlocks-handling.html) · MySQL · Recomendação de manter as transações pequenas e curtas e fazer commit logo após as alterações relacionadas, para reduzir conflitos - [Server Status Variables](https://dev.mysql.com/doc/refman/8.4/en/server-status-variables.html) · MySQL · Innodb_row_lock_waits e Innodb_row_lock_time mostram o número e o tempo de esperas por lock de linha; Innodb_row_lock_current_waits, quantas estão esperando agora - [The innodb_lock_waits and x$innodb_lock_waits Views](https://dev.mysql.com/doc/refman/8.4/en/sys-innodb-lock-waits.html) · MySQL · Query em espera (waiting_query), sessão que está bloqueando (blocking_pid), tempo de espera (wait_age) - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · wait_event_type do pg_stat_activity: Lock indica espera por um lock pesado (heavyweight lock) - [pg_locks (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/view-pg-locks.html) · PostgreSQL · granted em false indica que o processo está esperando para obter o lock - [Error Reporting and Logging (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-logging.html) · PostgreSQL · log_lock_waits: registra no log quando a espera por lock passa do deadlock_timeout; desligado por padrão #### db-deadlock · Deadlock no banco de dados · Database deadlock Quando duas transações (operações do BD processadas como um bloco único) esperam, cada uma, pela linha em que a outra pôs lock, o BD cancela uma delas à força. - Por quê → Efeito → Na tela: A troca A pega os locks na ordem item→moeda, e a B na ordem moeda→item → O BD detecta o deadlock e faz rollback de um dos lados → Trocas e crafting falham de vez em quando, e itens voltam - Sintomas: Ação perdida / rollback, Input lag / Fatores: Perda de pacotes, Paralisação - Quem: Só um recurso específico / Quando: Quando junta muita gente, Ao fazer ações específicas - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Padronizar a ordem dos locks, manter as transações curtas, repetir automaticamente em caso de falha. - O que fazer (Equipe de infraestrutura): Manter a detecção de deadlock ligada, coletar e compartilhar os registros de deadlock, reduzir o limite de espera por lock (padrão de 50 s) nos servidores MySQL com a detecção desligada. - Números de referência: A detecção é quase imediata no MySQL (InnoDB), leva 1 s por padrão no PostgreSQL e até cerca de 5 s no SQL Server. Enquanto isso, as duas requisições ficam paradas. Em servidores MySQL com a detecção desligada por causa de concorrência muito alta, a espera vai até o limite de espera por lock (padrão de 50 s). - No gráfico: Picos aleatórios (Número de deadlocks, falhas de troca) - Onde olhar: No MySQL, ver o LATEST DETECTED DEADLOCK do SHOW ENGINE INNODB STATUS (só o mais recente, 1 registro), todos os deadlocks gravados no log de erros com innodb_print_all_deadlocks ativado e o lock_deadlocks do INFORMATION_SCHEMA.INNODB_METRICS. No PostgreSQL, ver deadlocks em pg_stat_database; no SQL Server, o xml_deadlock_report da sessão system_health, ativa por padrão. Códigos de erro do lado do servidor do jogo: MySQL 1213, PostgreSQL 40P01, SQL Server 1205 - Confirma se: O número de deadlocks sobe nos horários das falhas de troca e crafting, e as duas transações registradas põem lock nas mesmas tabelas em ordens opostas - Descarta se: Número de deadlocks estável, mas com falhas: estouro do limite de espera por lock (erro 1205 do MySQL) ou hot row (db-hot-row) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [InnoDB Startup Options and System Variables](https://dev.mysql.com/doc/refman/8.4/en/innodb-parameters.html) · MySQL · Com a detecção ligada (padrão), o InnoDB detecta o deadlock na hora e faz rollback; innodb_lock_wait_timeout com padrão de 50 segundos - [Deadlock Detection](https://dev.mysql.com/doc/refman/8.4/en/innodb-deadlock-detection.html) · MySQL · Com concorrência muito alta, a própria detecção pode ficar lenta; às vezes ela é desligada, e o limite de espera por lock assume o papel - [Lock Management (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-locks.html) · PostgreSQL · deadlock_timeout com padrão de 1 segundo: só depois de esperar esse tempo pelo lock é feita a verificação de deadlock - [Deadlocks guide](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-deadlocks-guide) · Microsoft SQL Server · Intervalo padrão de verificação de deadlock de 5 segundos, que cai até 100 ms se os deadlocks forem frequentes; a sessão system_health, ativa por padrão, coleta o xml_deadlock_report; o lado sacrificado recebe o erro 1205 - [How to Minimize and Handle Deadlocks](https://dev.mysql.com/doc/refman/8.4/en/innodb-deadlocks-handling.html) · MySQL · Alterar várias linhas e tabelas sempre na mesma ordem, tentar de novo em caso de falha, registrar todos os deadlocks com innodb_print_all_deadlocks - [InnoDB Standard Monitor and Lock Monitor Output](https://dev.mysql.com/doc/refman/8.4/en/innodb-standard-monitor.html) · MySQL · LATEST DETECTED DEADLOCK: as duas transações do deadlock mais recente, os locks que seguravam e os que esperavam, e o lado que sofreu rollback - [InnoDB INFORMATION_SCHEMA Metrics Table](https://dev.mysql.com/doc/refman/8.4/en/innodb-information-schema-metrics-table.html) · MySQL · Contador lock_deadlocks do INNODB_METRICS (ativo por padrão) - [Server Error Message Reference](https://dev.mysql.com/doc/mysql-errors/8.4/en/server-error-reference.html) · MySQL · 1213 ER_LOCK_DEADLOCK (deadlock), 1205 ER_LOCK_WAIT_TIMEOUT (limite de espera por lock excedido) - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · deadlocks do pg_stat_database: número de deadlocks detectados neste banco - [PostgreSQL Error Codes (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/errcodes-appendix.html) · PostgreSQL · 40P01 deadlock_detected #### db-pool · Esgotamento do pool de conexões · Connection pool exhaustion O número de conexões abertas com o BD é fixo; quando queries lentas ocupam as conexões, as demais requisições esperam. - Por quê → Efeito → Na tela: Queries lentas ou um pico de requisições deixam todas as conexões ocupadas → Novas requisições esperam até uma conexão ficar livre → Login em loading infinito, salvamento atrasado, timeouts - Sintomas: Não conecta / loading infinito, Input lag / Fatores: Paralisação, Latência - Quem: Servidor inteiro, Só um recurso específico / Quando: Logo após login ou manutenção, Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Eliminar queries lentas, ajustar o tamanho do pool e o timeout de espera (sem aumentar o pool às cegas), separar pools por recurso. - O que fazer (Equipe de infraestrutura): Verificar o máximo de conexões do BD e a folga de CPU e IOPS, conferir antes de escalar ou ativar o autoscaling se número de servidores × tamanho do pool cabe no máximo de conexões, adicionar ao monitoramento métricas de espera por conexão e por lock. - Números de referência: Estima-se o número necessário de conexões por “requisições por segundo × tempo que cada uma ocupa a conexão”. Com 2.000 requisições por segundo e 5 ms cada, em média 10 conexões ficam sempre ocupadas. Para dar conta dos picos, em geral se reserva de 2 a 3 vezes esse número. Se as queries ficam lentas e passam a 150 ms, a mesma carga precisa de 300 conexões. - No gráfico: Achata ao bater no limite (Conexões do BD em uso, tempo de espera por conexão) - Onde olhar: Contar no BD o estado das conexões por servidor do jogo. No MySQL, ver Host, Command (conexões ociosas aparecem como Sleep) e Time no SHOW PROCESSLIST, além de Threads_connected, Threads_running e o número de conexões recusadas em Connection_errors_max_connections. No PostgreSQL, contar o pg_stat_activity agrupado por client_addr e state. Se a biblioteca de pool de conexões do servidor do jogo exporta o número e o tempo de espera, ver junto - Confirma se: Todas as conexões de um servidor do jogo, até o tamanho do pool, estão executando queries, com 0 conexões ociosas, e enquanto isso login e salvamento esperam. Ou o total de conexões do BD chega ao max_connections e novas conexões são recusadas - Descarta se: Lento mesmo com conexões ociosas de sobra: mais provável, latência da própria query (db-no-index, db-hot-row) ou saturação de recursos do BD - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Aumentar o pool às cegas só aumenta o uso de CPU do BD e a disputa por locks, e todos ficam lentos juntos. Além disso, se número de servidores × tamanho do pool passar do máximo de conexões do BD, servidores novos ou reiniciados não conseguem nem abrir conexão. Isso é comum logo após autoscaling ou manutenção. - Fontes: - [Number Of Database Connections](https://wiki.postgresql.org/wiki/Number_Of_Database_Connections) · PostgreSQL · Depois que os recursos do BD se esgotam, mais conexões chegam a reduzir a vazão; ajustar as conexões ativas aos recursos e deixar o resto na fila melhora tanto a latência quanto a vazão - [Too many connections](https://dev.mysql.com/doc/refman/8.4/en/too-many-connections.html) · MySQL · Com todo o max_connections em uso, novas conexões são recusadas com o erro Too many connections - [Connections and Authentication (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-connection.html) · PostgreSQL · max_connections: limite de conexões simultâneas, em geral 100 por padrão - [SHOW PROCESSLIST Statement](https://dev.mysql.com/doc/refman/8.4/en/show-processlist.html) · MySQL · Host (endereço do cliente), Command (sessões ociosas aparecem como Sleep), Time, State - [Server Status Variables](https://dev.mysql.com/doc/refman/8.4/en/server-status-variables.html) · MySQL · Threads_connected e Threads_running, Connection_errors_max_connections (conexões recusadas por atingir max_connections) - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · pg_stat_activity: client_addr e state (active, idle, idle in transaction etc.) de cada conexão #### db-replica-lag · Atraso de replicação · Replication lag Com as escritas no BD primário e as leituras em uma réplica, se a réplica fica para trás, o que acabou de ser gravado não aparece. - Por quê → Efeito → Na tela: Um volume grande de escritas no BD primário deixa a réplica alguns segundos atrasada → O que acabou de ser salvo ainda não está na réplica quando é lido de lá → O item que você acabou de comprar não aparece, o preço no mercado está desatualizado, bug de entrega duplicada - Sintomas: Ação perdida / rollback / Fatores: Latência - Quem: Só um recurso específico / Quando: Quando junta muita gente, Horário de pico à noite - Responsável principal: Infraestrutura de banco de dados (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Ler do BD primário os dados que acabaram de ser gravados, verificar se a recompensa já foi entregue e entregá-la em uma única transação no BD primário (bloquear duplicação com chave única ou UPDATE condicional). - O que fazer (Equipe de infraestrutura): Criar alerta de atraso de replicação, dar à réplica uma configuração igual ou superior à do BD primário e ativar replicação paralela, executar exclusões em massa em pedaços pequenos, controlar queries de agregação longas na réplica. - No gráfico: Sobe com a carga (Atraso de replicação (s)) - Onde olhar: No MySQL, ver Seconds_Behind_Source no SHOW REPLICA STATUS da réplica (SHOW SLAVE STATUS em versões anteriores à 8.0.22). No PostgreSQL, ver write_lag, flush_lag e replay_lag no pg_stat_replication do servidor primário; no RDS, ReplicaLag - Confirma se: No horário dos reports de “não aparece”, o atraso está em alguns segundos ou mais, e depois que o atraso some tudo aparece normal. O atraso cresce nos horários de pico de escritas, exclusões em massa ou queries de agregação longas na réplica - Descarta se: Atraso perto de 0 e mesmo assim não aparece: mais provável, cache ou sincronização do servidor do jogo - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: A réplica pode ficar para trás mesmo sem muitas escritas. Uma única exclusão em massa que levou 10 minutos no BD primário deixa a réplica atrasada nesse mesmo tempo enquanto é reexecutada lá, e queries de agregação longas rodando nela também retardam a recuperação do atraso. - Fontes: - [SHOW REPLICA STATUS Statement](https://dev.mysql.com/doc/refman/8.4/en/show-replica-status.html) · MySQL · Seconds_Behind_Source: diferença em relação ao horário em que o evento que a réplica está aplicando agora foi gravado no BD primário (atraso de replicação) - [Replica Server Options and Variables](https://dev.mysql.com/doc/refman/8.4/en/replication-options-replica.html) · MySQL · Com replica_parallel_workers, várias threads aplicam as transações em paralelo (padrão 4; com 0, uma única thread aplica em ordem) - [Log-Shipping Standby Servers (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/warm-standby.html) · PostgreSQL · A replicação por streaming é assíncrona por padrão, então há atraso entre o commit e a réplica refletir a mudança (em geral menos de 1 segundo, se a réplica consegue acompanhar) - [MySQL 8.0 Reference Manual: SHOW REPLICA STATUS Statement](https://dev.mysql.com/doc/refman/8.0/en/show-replica-status.html) · MySQL · A partir da 8.0.22, SHOW REPLICA STATUS substitui SHOW SLAVE STATUS; versões anteriores usam SHOW SLAVE STATUS - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · write_lag, flush_lag e replay_lag do pg_stat_replication: tempo entre o servidor primário gravar o WAL e a réplica avisar que o escreveu, gravou no disco e aplicou - [Amazon CloudWatch metrics for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-metrics.html) · AWS · ReplicaLag: quanto a réplica de leitura está atrasada em relação à origem (segundos) #### db-checkpoint · Checkpoint e flush de log · Checkpoint / log flush stalls O BD grava periodicamente no disco, de uma vez, as alterações acumuladas na memória, e nesse momento as queries ficam lentas. - Por quê → Efeito → Na tela: As alterações se acumulam e são gravadas no disco periodicamente → Nesse momento o disco fica ocupado e as queries atrasam → Salvamentos e carregamentos ficam lentos em intervalos regulares - Sintomas: Input lag, Engasgos / Fatores: Latência - Quem: Servidor inteiro, Só um recurso específico / Quando: Em intervalos regulares - Responsável principal: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Dividir os checkpoints em partes menores e espalhá-los, dar folga ao log de transações (redo log, WAL), usar disco rápido. - No gráfico: Picos em intervalos regulares (Latência das queries do BD, volume de escrita no disco) - Onde olhar: No PostgreSQL, ver no log do log_checkpoints (ativo por padrão nas versões recentes) o horário de cada checkpoint e o número de buffers gravados, o número de checkpoints (num_timed e num_requested do pg_stat_checkpointer a partir da 17; checkpoints_timed e checkpoints_req do pg_stat_bgwriter na 16 e anteriores) e os avisos de checkpoint_warning. No MySQL, ver na seção LOG do SHOW ENGINE INNODB STATUS a diferença entre Log sequence number e Last checkpoint at. Sobrepor o volume e a latência de escrita no disco do servidor - Confirma se: Os picos de latência das queries coincidem com os checkpoints, e nesse momento o volume e a latência de escrita no disco disparam. No PostgreSQL, se os checkpoints por requisição (num_requested) forem muito mais numerosos que os por tempo (num_timed), o WAL está batendo com frequência no max_wal_size e antecipando os checkpoints - Descarta se: Picos em intervalos sem relação com os checkpoints: backup ou jobs em lote (dk-backup, db-batch) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Se o log de transações que guarda o registro das alterações (redo log no MySQL, WAL no PostgreSQL) for pequeno demais, o BD faz checkpoints às pressas toda vez que o log enche, e a vazão de escrita cai muito por alguns instantes. - Fontes: - [WAL Configuration (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/wal-configuration.html) · PostgreSQL · Checkpoint a cada 5 minutos ou 1 GB de WAL (max_wal_size) por padrão; é caro porque grava todas as páginas sujas. checkpoint_completion_target distribui as escritas e evita picos de I/O. Se o intervalo entre checkpoints for menor que checkpoint_warning, um aviso no log recomenda aumentar o max_wal_size - [Configuring Buffer Pool Flushing](https://dev.mysql.com/doc/refman/8.4/en/innodb-buffer-pool-flushing.html) · MySQL · Quando o redo log enche, um checkpoint às pressas (sharp checkpoint) derruba a vazão por um momento; o flush adaptativo distribui as escritas de forma uniforme - [Error Reporting and Logging (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-logging.html) · PostgreSQL · log_checkpoints: registra no log, a cada checkpoint, o número de buffers gravados e o tempo gasto; ativo por padrão - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · num_timed (checkpoints feitos por tempo) e num_requested (checkpoints solicitados) do pg_stat_checkpointer - [PostgreSQL 17 Release Notes](https://www.postgresql.org/docs/release/17.0/) · PostgreSQL · Criação do pg_stat_checkpointer, com as colunas de checkpoint movidas do pg_stat_bgwriter - [The Cumulative Statistics System (PostgreSQL 16 Documentation)](https://www.postgresql.org/docs/16/monitoring-stats.html) · PostgreSQL · Até a 16, checkpoints_timed e checkpoints_req do pg_stat_bgwriter - [InnoDB Standard Monitor and Lock Monitor Output](https://dev.mysql.com/doc/refman/8.4/en/innodb-standard-monitor.html) · MySQL · Seção LOG: número de sequência do log atual e posição do último checkpoint #### db-cold-cache · Cache frio (logo após reiniciar) · Cold buffer pool after restart Quando o BD reinicia, o cache em memória está vazio, e por um tempo todas as leituras vêm do disco. - Por quê → Efeito → Na tela: O BD reinicia na manutenção → Os dados usados com frequência não estão na memória e são lidos do disco → Login e carregamento lentos por um tempo logo após a manutenção - Sintomas: Não conecta / loading infinito, Input lag / Fatores: Latência - Quem: Servidor inteiro / Quando: Logo após login ou manutenção - Responsável principal: Infraestrutura de banco de dados (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Abertura gradual (aumentar aos poucos o número de logins com a fila de login). - O que fazer (Equipe de infraestrutura): Aquecer o cache depois do reinício (warm-up; verificar a configuração de salvar e restaurar o buffer pool), ler antecipadamente o disco de BDs restaurados a partir de snapshot. - No gráfico: Pico logo após abrir ou manutenção (Leituras de disco, taxa de acerto do buffer cache) - Onde olhar: No MySQL, ver a proporção entre Innodb_buffer_pool_reads (leituras que foram ao disco porque a página não estava no buffer pool) e Innodb_buffer_pool_read_requests, e o progresso do aquecimento em Innodb_buffer_pool_load_status. No PostgreSQL, ver blks_read e blks_hit no pg_stat_database. Ver também o número de leituras de disco do servidor do BD - Confirma se: Logo após o reinício, as leituras de disco disparam e a taxa de acerto fica baixa, depois se recupera com o tempo, e nesse período login e carregamento ficam lentos - Descarta se: Taxa de acerto normal, mas lento logo após a manutenção: avalanche de logins e N+1 (db-login-storm) ou pool de conexões (db-pool) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O MySQL salva a lista de páginas do buffer pool ao desligar e as lê de volta em segundo plano ao ligar, mas leva tempo até encher tudo. Se o BD foi restaurado a partir de um snapshot (cópia do disco) na nuvem, o próprio disco é lento a cada bloco lido pela primeira vez, e o problema dura mais. - Casos reais: roblox-2021 - Fontes: - [Saving and Restoring the Buffer Pool State](https://dev.mysql.com/doc/refman/8.4/en/innodb-preload-buffer-pool.html) · MySQL · Para encurtar o aquecimento após o reinício, salva ao desligar a lista das páginas usadas recentemente (padrão de 25%) e a lê de volta ao ligar; as duas opções vêm ativadas por padrão - [pg_prewarm — preload relation data into buffer caches](https://www.postgresql.org/docs/current/pgprewarm.html) · PostgreSQL · Grava periodicamente o conteúdo dos shared buffers e o carrega de volta após o reinício (autoprewarm) - [Initialize Amazon EBS volumes](https://docs.aws.amazon.com/ebs/latest/userguide/ebs-initialize.html) · AWS · Volumes criados a partir de snapshot têm latência maior e desempenho menor até todos os blocos serem buscados - [Server Status Variables](https://dev.mysql.com/doc/refman/8.4/en/server-status-variables.html) · MySQL · Innodb_buffer_pool_reads (leituras lógicas que tiveram de ir direto ao disco porque a página não estava no buffer pool), Innodb_buffer_pool_read_requests, Innodb_buffer_pool_load_status (progresso do aquecimento) - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · blks_read (blocos lidos do disco) e blks_hit (blocos encontrados no buffer cache) do pg_stat_database #### db-login-storm · Avalanche de logins e queries N+1 · Login storm, N+1 queries Se carregar um personagem exige dezenas de consultas separadas, dezenas de milhares de logins simultâneos viram milhões de queries. - Por quê → Efeito → Na tela: Ao carregar um personagem, itens, skills e quests são consultados um a um, separadamente → Os logins simultâneos logo após a manutenção fazem as queries explodirem → Login em loading infinito, e até o salvamento de quem já está jogando fica na fila - Sintomas: Não conecta / loading infinito, Input lag / Fatores: Paralisação, Latência - Quem: Servidor inteiro / Quando: Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Consultar tudo de uma vez em lote, usar fila de login e cache, verificar o número de consultas gerado pelo lazy loading do ORM. - O que fazer (Equipe de infraestrutura): Levantar e compartilhar o ranking das queries mais chamadas, monitorar o número de queries e de conexões no horário de login logo após a manutenção. - No gráfico: Pico logo após abrir ou manutenção (Queries por segundo no BD, logins) - Onde olhar: Sobrepor o número de logins logo após a manutenção às queries por segundo do BD (no MySQL, o aumento de Questions) e calcular quantas queries cada login gera. Levantar as queries mais chamadas pelo COUNT_STAR do events_statements_summary_by_digest no MySQL ou pelo calls do pg_stat_statements no PostgreSQL - Confirma se: Cada login gera dezenas de queries, e as mais chamadas são queries curtas de mesmo formato que consultam por um único ID de personagem. Se o número de queries por login aumentou depois de um patch, esse patch é o ponto de partida - Descarta se: Poucas queries por login, mas cada uma lenta: cache frio (db-cold-cache) ou índice (db-no-index) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O lazy loading do ORM (biblioteca que monta as consultas ao BD no lugar do desenvolvedor) gera esse tipo de consulta sem que nem o desenvolvedor perceba. No servidor de desenvolvimento, com poucos personagens, nada aparece; o problema só surge com os logins simultâneos em produção. - Fontes: - [Efficient Querying](https://learn.microsoft.com/en-us/ef/core/performance/efficient-querying) · .NET · O lazy loading do ORM cria o problema N+1, que envia uma query a mais para cada item e derruba muito o desempenho; recomenda-se carregar tudo de uma vez (eager loading) - [pg_stat_statements — track statistics of SQL planning and execution](https://www.postgresql.org/docs/current/pgstatstatements.html) · PostgreSQL · Agrega o número de execuções (calls) e o tempo total de cada comando para levantar o ranking das queries mais chamadas - [Performance Schema Statement Digests and Sampling](https://dev.mysql.com/doc/refman/8.4/en/performance-schema-statement-digests.html) · MySQL · events_statements_summary_by_digest agrupa queries de mesmo formato e soma execuções e tempo - [Statement Summary Tables](https://dev.mysql.com/doc/refman/8.4/en/performance-schema-statement-summary-tables.html) · MySQL · COUNT_STAR (número de execuções) e SUM_TIMER_WAIT (tempo total) das tabelas de resumo - [Server Status Variables](https://dev.mysql.com/doc/refman/8.4/en/server-status-variables.html) · MySQL · Questions: número de comandos enviados pelos clientes #### db-batch · Jobs em lote pesados · Batch jobs during service Rodar com o jogo no ar o cálculo de rankings, o envio de correio em massa ou a limpeza de dados antigos ocupa locks e disco. - Por quê → Efeito → Na tela: Um job pesado roda com o jogo no ar → Locks em faixas amplas, disco e CPU ocupados → Falhas de troca e de salvamento em certos horários, carregamento lento - Sintomas: Input lag, Ação perdida / rollback / Fatores: Latência, Paralisação - Quem: Só um recurso específico, Servidor inteiro / Quando: Em intervalos regulares - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Dividir em partes pequenas e processar aos poucos, fazer as agregações na réplica. - O que fazer (Equipe de infraestrutura): Oferecer uma réplica para agregações, agendar os jobs em lote para horários tranquilos, monitorar lock escalation e esperas por gap lock. - No gráfico: Picos em intervalos regulares (Latência das queries do BD, esperas por lock) - Onde olhar: Encontrar as queries longas que rodavam no horário do lag. No MySQL, ver o slow query log; no PostgreSQL, query_start e query no pg_stat_activity; comparar com as métricas de espera por lock do mesmo horário e com a agenda dos jobs em lote (cron, event scheduler do BD). No SQL Server, registrar o lock escalation com o evento estendido lock_escalation - Confirma se: Sempre no mesmo horário rodam UPDATE, DELETE ou queries de agregação em massa, e enquanto isso as esperas por lock e a utilização do disco sobem juntas - Descarta se: Nenhuma query longa nesse horário: checkpoint (db-checkpoint) ou backup do servidor (dk-backup) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: No SQL Server, quando um comando segura mais de cerca de 5.000 locks de linha, eles viram um lock de tabela (lock escalation). Nesse instante, todas as requisições que usam a mesma tabela param. No MySQL, com a configuração padrão, alterar por uma condição de faixa também põe lock nos intervalos entre as linhas (gap lock) e impede a inserção de linhas novas. - Fontes: - [Transaction Locking and Row Versioning Guide](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-transaction-locking-and-row-versioning-guide) · Microsoft SQL Server · Lock escalation quando um comando segura 5.000 locks ou mais em uma tabela (ou índice); registrado pelo evento estendido lock_escalation - [InnoDB Locking](https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html) · MySQL · No nível de isolamento padrão do InnoDB, REPEATABLE READ, buscas e varreduras usam next-key locks, e o gap lock impede inserir linhas novas naquele intervalo - [The Slow Query Log](https://dev.mysql.com/doc/refman/8.4/en/slow-query-log.html) · MySQL · Registra as queries que passam do long_query_time com o tempo de execução (Query_time), o tempo de lock (Lock_time) e o número de linhas lidas - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · pg_stat_activity: query em execução (query) e horário de início (query_start) de cada sessão #### db-failover · Failover do banco de dados · Database failover Quando o BD primário cai, não dá para gravar durante a troca para o BD reserva, e os últimos dados que não foram replicados podem se perder. - Por quê → Efeito → Na tela: Uma falha no BD primário faz o BD reserva ser promovido → Durante a troca, escrita indisponível por alguns segundos a alguns minutos; com replicação assíncrona, dados não replicados podem se perder → Todos os salvamentos falham por um momento, rollback de itens e experiência - Sintomas: Ação perdida / rollback, Travamento, Desconexão, Não conecta / loading infinito / Fatores: Paralisação, Perda de pacotes - Quem: Servidor inteiro / Quando: Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de banco de dados (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Fazer salvamentos que possam ser repetidos com segurança, configurar para descartar rápido as conexões quebradas e reconectar no novo endereço (pool de conexões, cache de DNS), verificar a reconexão nos treinamentos de failover. - O que fazer (Equipe de infraestrutura): Usar replicação síncrona ou semissíncrona (em troca de mais latência de escrita), fazer treinamentos de failover, monitorar o tempo de failover e o atraso de replicação. - Números de referência: O failover automático de um BD gerenciado leva em geral de dezenas de segundos a 2 minutos. Com replicação assíncrona, dá para perder os salvamentos mais recentes, na medida do atraso de replicação (de menos de 1 s a alguns segundos). - No gráfico: Queda de conexões em massa (Conexões com o BD, erros de escrita) - Onde olhar: Colocar no mesmo gráfico os registros de failover do BD (no RDS, os eventos RDS-EVENT-0013, início do failover, e RDS-EVENT-0049, failover concluído; em BD autogerenciado, o log de promoção) e o número de conexões e de erros de conexão com o BD nos servidores do jogo. Com replicação assíncrona, ver também o atraso de replicação logo antes da falha (ReplicaLag no RDS, replay_lag no pg_stat_replication do PostgreSQL) - Confirma se: As falhas de salvamento se concentram em um intervalo que coincide com o período entre o início e a conclusão do failover. O volume revertido é parecido com o atraso de replicação logo antes da falha. Servidores do jogo que continuam com erro depois do failover ainda estão usando conexões abertas com o endereço antigo - Descarta se: Conexões caindo em horários sem registro de failover: mais provável, rede ou sobrecarga do BD - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Casos reais: riot-euw-2021 - Fontes: - [Failing over a Multi-AZ DB instance for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.Failover.html) · AWS · Failover Multi-AZ leva em geral 60–120 segundos; depois dele é preciso reconectar, e recomenda-se TTL de cache de DNS da JVM de no máximo 60 segundos - [High availability for Amazon Aurora](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Concepts.AuroraHighAvailability.html) · AWS · Durante a falha, leituras e escritas falham, e a recuperação costuma acontecer em até 60 segundos (muitas vezes em até 30) - [Semisynchronous Replication](https://dev.mysql.com/doc/refman/8.4/en/replication-semisync.html) · MySQL · Com replicação assíncrona, se o BD primário cai, transações já confirmadas podem não estar na réplica; a semissíncrona reduz esse risco esperando a confirmação de recebimento de uma réplica, em troca de mais latência - [Log-Shipping Standby Servers (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/warm-standby.html) · PostgreSQL · O envio de logs é assíncrono, então, se o servidor primário cai, as transações ainda não enviadas se perdem; o atraso da replicação por streaming costuma ser menor que 1 segundo - [Amazon RDS event categories and event messages](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Events.Messages.html) · AWS · RDS-EVENT-0013: início do failover Multi-AZ; RDS-EVENT-0049: failover Multi-AZ concluído - [Amazon CloudWatch metrics for Amazon RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-metrics.html) · AWS · ReplicaLag: quanto a réplica de leitura está atrasada em relação à origem (segundos) - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · replay_lag do pg_stat_replication: tempo entre o servidor primário gravar o WAL e a réplica avisar que o aplicou #### db-save-interval · Perda de progresso por intervalo de salvamento longo · Periodic save window Se, para reduzir a carga, o salvamento só acontece a cada alguns minutos, uma queda do servidor nesse intervalo apaga o progresso. - Por quê → Efeito → Na tela: O estado do personagem é salvo uma vez a cada alguns minutos → Nesse intervalo, o servidor sofre um crash ou uma falha → Ao reconectar, o personagem está como estava alguns minutos antes (rollback) - Sintomas: Ação perdida / rollback / Fatores: Perda de pacotes - Quem: Servidor inteiro, Local ou canal específico / Quando: Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Salvar na hora os eventos importantes (trocas, drops raros), registrar um log de alterações. - O que fazer (Equipe de infraestrutura): Verificar se o BD tem folga de IOPS e CPU para aguentar as escritas extras de um intervalo de salvamento menor. - No gráfico: Queda de conexões em massa (Número de conexões, reports de rollback) - Onde olhar: Colocar lado a lado o horário do crash ou da falha e o último salvamento dos personagens com rollback reportado (log de salvamento do servidor do jogo ou coluna de data de alteração no BD) - Confirma se: O ponto para onde o personagem voltou coincide com o último salvamento antes do crash, e o tempo perdido é menor que o intervalo de salvamento - Descarta se: O log do servidor do jogo registra o salvamento como concluído e mesmo assim houve rollback: perda de dados no failover do BD (db-failover) ou valor antigo lido da réplica (db-replica-lag) - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Asynchronous Commit (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/wal-async-commit.html) · PostgreSQL · Acumular gravações e enviá-las ao disco mais tarde aumenta a vazão, mas numa falha as transações mais recentes podem se perder (o mesmo trade-off) - [Redis persistence](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/) · Redis · Se o snapshot RDB é feito a cada alguns minutos, é preciso aceitar perder os últimos minutos de dados num encerramento anormal #### db-cache-stampede · Cache stampede · Cache stampede / thundering herd Quando o cache de dados populares expira todo ao mesmo tempo, milhares de requisições caem de uma vez no BD. - Por quê → Efeito → Na tela: Dados populares guardados no Redis ou similar expiram ao mesmo tempo → As requisições que tentam recriar os mesmos dados caem todas de uma vez no BD → Com o BD sobrecarregado, vários recursos ficam lentos ou param, um atrás do outro - Sintomas: Input lag, Travamento, Não conecta / loading infinito / Fatores: Paralisação, Latência - Quem: Servidor inteiro / Quando: Em intervalos regulares, Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Espalhar aleatoriamente os horários de expiração, deixar só uma requisição atualizar enquanto as demais usam o valor antigo. - O que fazer (Equipe de infraestrutura): Configurar réplica e failover automático para o cache não esvaziar por inteiro quando o Redis reinicia ou falha, verificar se o BD tem folga para aguentar mesmo com o cache vazio. - No gráfico: Picos em intervalos regulares (Taxa de acerto do cache, queries por segundo no BD) - Onde olhar: Sobrepor às queries por segundo do BD os valores keyspace_hits e keyspace_misses (taxa de acerto), expired_keys e o reinício (uptime_in_seconds) do INFO do Redis, e contar quantas cópias da mesma query rodam ao mesmo tempo no BD nesse instante (SHOW PROCESSLIST no MySQL, pg_stat_activity no PostgreSQL) - Confirma se: No instante em que os cache misses disparam, as queries do BD disparam junto, e a maior parte das queries simultâneas é a mesma query lendo os mesmos dados. Coincide com o ciclo de expiração de uma chave popular ou com um reinício do Redis - Descarta se: Cache misses normais, mas só as queries do BD aumentam: avalanche de logins (db-login-storm) ou jobs em lote (db-batch) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O mesmo acontece quando o Redis reinicia ou falha e o cache esvazia por inteiro. Quanto mais a arquitetura confia no cache e mantém o BD pequeno, maior o risco. - Fontes: - [Scaling Memcache at Facebook (NSDI '13)](https://www.usenix.org/conference/nsdi13/technical-sessions/presentation/nishtala) · USENIX · Quando uma chave muito usada é invalidada, muitas leituras caem no BD (thundering herd); evitado com leases (só um cliente atualiza) e devolução do valor antigo; clusters com cache vazio são aquecidos à parte - [Optimal Probabilistic Cache Stampede Prevention](https://www.vldb.org/pvldb/vol8/p886-vattani.pdf) · VLDB Endowment · Quando um item popular expira, várias requisições o recriam ao mesmo tempo (cache stampede); evitado atualizando de forma probabilística antes da expiração - [High availability with Redis Sentinel](https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/) · Redis · Failover automático que promove uma réplica quando o servidor primário cai - [INFO](https://redis.io/docs/latest/commands/info/) · Redis · keyspace_hits e keyspace_misses (buscas de chave com sucesso e com falha), expired_keys (chaves expiradas), uptime_in_seconds (tempo desde a inicialização) - [SHOW PROCESSLIST Statement](https://dev.mysql.com/doc/refman/8.4/en/show-processlist.html) · MySQL · Comando em execução (Info) e tempo no estado atual (Time, em segundos) de cada sessão - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · pg_stat_activity: query em execução (query) de cada sessão #### db-long-tx · Transação aberta por muito tempo · Long-running transaction / MVCC purge lag Uma transação aberta por muito tempo continua segurando locks, e o BD não consegue limpar as versões antigas dos dados (purge), então tudo vai ficando mais lento. - Por quê → Efeito → Na tela: Uma transação fica aberta enquanto espera a resposta de outro servidor, ou uma query de agregação longa roda no BD primário durante a operação → Os locks não são liberados, e as versões antigas que precisam ser limpas continuam se acumulando → Timeout nos recursos que usam aquela linha; ao longo de horas, salvamentos e consultas ficam lentos de modo geral - Sintomas: Input lag, Ação perdida / rollback / Fatores: Latência, Paralisação - Quem: Só um recurso específico, Servidor inteiro / Quando: Quanto mais tempo ligado, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Não esperar chamadas de rede nem input do usuário dentro de uma transação, rodar queries de agregação na réplica. - O que fazer (Equipe de infraestrutura): Criar alerta para transações abertas por muito tempo e encerrá-las à força, oferecer uma réplica para agregações, monitorar o crescimento do undo log e das linhas mortas. - No gráfico: Subida lenta (Tamanho do undo log (History list length), linhas mortas) - Onde olhar: No MySQL, achar a transação mais antiga pelo trx_started do INFORMATION_SCHEMA.INNODB_TRX e ver o History list length (undo log ainda não limpo) na seção TRANSACTIONS do SHOW ENGINE INNODB STATUS. No PostgreSQL, ver o xact_start e as sessões com state idle in transaction no pg_stat_activity, e o n_dead_tup no pg_stat_user_tables - Confirma se: Há uma transação aberta há minutos ou horas, e durante esse tempo o History list length ou o n_dead_tup sobem sem parar; depois que a transação termina e a limpeza (purge, VACUUM) roda, eles caem - Descarta se: Nenhuma transação antiga, mas tudo lento: mais provável, checkpoint (db-checkpoint) ou disco - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O BD guarda versões antigas para que quem lê possa ver os dados como eram antes da alteração (MVCC). Esse histórico só pode ser apagado quando a transação mais antiga termina, então, se uma transação fica aberta por horas, acumula-se undo log no MySQL e linhas mortas (dead tuples) que o VACUUM não conseguiu limpar no PostgreSQL. No SQL Server, o log de transações não diminui e pode até encher o disco. - Fontes: - [InnoDB Multi-Versioning](https://dev.mysql.com/doc/refman/8.4/en/innodb-multi-versioning.html) · MySQL · Enquanto houver transações que podem ver versões antigas, o undo log de update não pode ser descartado e o rollback segment cresce; recomenda-se fazer commit com frequência mesmo em transações só de leitura - [Routine Vacuuming (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/routine-vacuuming.html) · PostgreSQL · Versões antigas de linhas não podem ser apagadas enquanto outras transações puderem vê-las; transações abertas por muito tempo precisam ser finalizadas ou ter a sessão encerrada - [Client Connection Defaults (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-client.html) · PostgreSQL · idle_in_transaction_session_timeout: encerra sessões ociosas com transação aberta para que não segurem locks por muito tempo - [Troubleshoot a full transaction log (SQL Server Error 9002)](https://learn.microsoft.com/en-us/sql/relational-databases/logs/troubleshoot-a-full-transaction-log-sql-server-error-9002) · Microsoft SQL Server · Transações ativas de longa duração impedem a limpeza do log de transações - [The INFORMATION_SCHEMA INNODB_TRX Table](https://dev.mysql.com/doc/refman/8.4/en/information-schema-innodb-trx-table.html) · MySQL · TRX_STARTED: horário de início da transação - [Purge Configuration](https://dev.mysql.com/doc/refman/8.4/en/innodb-purge-configuration.html) · MySQL · O purge limpa a lista de undo logs das transações confirmadas (history list); o volume pendente aparece como History list length na seção TRANSACTIONS do SHOW ENGINE INNODB STATUS - [The Cumulative Statistics System (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/monitoring-stats.html) · PostgreSQL · xact_start (início da transação) e state (idle in transaction) do pg_stat_activity, n_dead_tup (estimativa de linhas mortas) do pg_stat_user_tables #### db-redis-block · Comandos lentos no Redis · Redis blocking commands (single-threaded) O Redis processa um comando de cada vez, então um único comando lento bloqueia todas as requisições que vêm atrás. - Por quê → Efeito → Na tela: Busca completa com KEYS durante a operação, ou leitura ou exclusão de uma vez de rankings e listas com milhões de elementos → Até esse comando terminar, todas as outras requisições esperam (de dezenas de ms a alguns segundos) → Engasgos simultâneos nos recursos que usam sessão, ranking e cache; login lento - Sintomas: Travamento, Input lag, Não conecta / loading infinito / Fatores: Paralisação, Latência - Quem: Servidor inteiro, Só um recurso específico / Quando: Aleatoriamente, de vez em quando, Em intervalos regulares - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Trocar KEYS por SCAN, dividir chaves grandes, apagar com UNLINK (exclusão em segundo plano), espalhar expirações concentradas no mesmo segundo. - O que fazer (Equipe de infraestrutura): Monitorar o log de comandos lentos (SLOWLOG), bloquear comandos perigosos como KEYS nos servidores de produção, verificar chaves grandes periodicamente, desligar o THP e garantir folga de memória para o fork, fazer o salvamento RDB e AOF na réplica. - Números de referência: Comandos comuns levam menos de 1 ms. Lidar com milhões de elementos de uma vez pode levar de centenas de ms a alguns segundos. - No gráfico: Picos aleatórios (Latência de resposta do Redis, comandos lentos) - Onde olhar: Ver com SLOWLOG GET os comandos que passaram do slowlog-log-slower-than e, depois de ligar o monitor de latência (desligado por padrão) com CONFIG SET latency-monitor-threshold, ver a latência por evento, como fork e expire-cycle, com LATENCY LATEST e LATENCY DOCTOR. Conferir também o tempo de fork e as chaves grandes com o latest_fork_usec do INFO e o redis-cli --bigkeys - Confirma se: No horário da parada, o SLOWLOG tem KEYS ou comandos que manipulam uma chave grande inteira, ou o LATENCY registra no mesmo horário eventos de fork ou expire-cycle de dezenas de ms ou mais - Descarta se: SLOWLOG e LATENCY vazios, mas lento só do lado do servidor do jogo: rede ou espera dentro do servidor do jogo (o SLOWLOG mede só o tempo de execução do comando, sem o tempo de troca de dados com o cliente) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O Redis também para no momento em que duplica o processo (fork) para gerar o arquivo de salvamento (snapshot RDB) ou reescrever o AOF. Nos servidores atuais, isso leva cerca de 10 ms a cada 1 GB de memória, ou seja, uns 300 ms para 30 GB. Com páginas grandes (THP) ligadas, cada escrita depois do fork copia uma página grande inteira (copy-on-write), o que aumenta muito a pausa e o uso de memória; por isso, em geral se desliga o THP e se deixa bastante folga de memória. Quando muitas chaves expiram no mesmo segundo, o Redis também para por um instante para apagá-las. - Fontes: - [Diagnosing latency issues](https://redis.io/docs/latest/operate/oss_and_stack/management/optimization/latency/) · Redis · Uma única thread processa as requisições em sequência, e um comando lento bloqueia todas as seguintes; trocar KEYS por SCAN; o fork medido em servidores físicos e VMs modernas leva cerca de 9–13 ms a cada 1 GB; o THP causa picos de latência e de memória por causa da cópia depois do fork; expiração em massa no mesmo segundo causa paradas - [KEYS](https://redis.io/docs/latest/commands/keys/) · Redis · Usar com extremo cuidado em produção, pois pode arruinar o desempenho em bancos grandes (40 ms para 1 milhão de chaves em um notebook de entrada) - [UNLINK](https://redis.io/docs/latest/commands/unlink/) · Redis · Exclusão assíncrona que desvincula a chave na hora e recupera a memória em outra thread - [SLOWLOG](https://redis.io/docs/latest/commands/slowlog/) · Redis · Log de comandos lentos que registra os comandos que passam do slowlog-log-slower-than; o tempo de execução não inclui o I/O de troca de dados com o cliente - [Redis latency monitoring](https://redis.io/docs/latest/operate/oss_and_stack/management/optimization/latency-monitor/) · Redis · latency-monitor-threshold com padrão 0 (desligado), LATENCY LATEST e LATENCY DOCTOR, registro da latência por evento, como fork e expire-cycle - [INFO](https://redis.io/docs/latest/commands/info/) · Redis · latest_fork_usec: duração do último fork (microssegundos) - [Redis CLI](https://redis.io/docs/latest/develop/tools/cli/) · Redis · --bigkeys: varre o keyspace e encontra chaves grandes #### db-plan-flip · Query lenta por mudança no plano de execução · Query plan regression (stats, parameter sniffing) O código continua igual, mas, se o BD muda a forma de executar a mesma query (plano de execução), uma query que levava 2 ms ontem passa a levar centenas de ms hoje. - Por quê → Efeito → Na tela: Atualização automática de estatísticas, reinício do BD ou mudança na distribuição dos dados levam o BD a montar um novo plano de execução → É escolhido um plano que não usa índice, a mesma query fica de dezenas a centenas de vezes mais lenta e as conexões ficam presas → Sem nenhum deploy, o carregamento de um recurso específico fica lento de repente, e outras requisições também esperam - Sintomas: Input lag, Não conecta / loading infinito / Fatores: Latência, Paralisação - Quem: Só um recurso específico, Servidor inteiro / Quando: Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de banco de dados (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Separar as queries cujo número de resultados varia muito conforme o valor ou avaliar hints de plano, projetar queries que com certeza usem índice. - O que fazer (Equipe de infraestrutura): Monitorar queries lentas e o histórico de planos de execução, fixar os planos bons (Query Store do SQL Server etc.), controlar o horário de atualização das estatísticas. - No gráfico: Degrau a partir de um momento (Tempo médio de execução por query) - Onde olhar: Coletar periodicamente o tempo médio de queries de mesmo formato e acompanhar a tendência: AVG_TIMER_WAIT do events_statements_summary_by_digest no MySQL, mean_exec_time do pg_stat_statements no PostgreSQL (mean_time na 12 e anteriores). Comparar os planos de execução de antes e depois da lentidão com EXPLAIN ou auto_explain do PostgreSQL; no SQL Server, com a tela de consultas regredidas (Regressed Queries) do Query Store - Confirma se: Sem nenhum deploy, o tempo médio de uma query sobe em degrau, dezenas de vezes, num momento que coincide com uma atualização de estatísticas ou um reinício do BD, e o plano de execução mudou - Descarta se: Plano de execução igual, mas mais lento: crescimento dos dados, espera por lock (db-hot-row) ou disco - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O SQL Server reutiliza o plano montado para o primeiro valor recebido (parameter sniffing). Um plano montado para um personagem novo com poucos itens fica muito lento quando é usado para um personagem antigo com dezenas de milhares de itens, e o caso contrário também é comum. Às vezes o reinício apaga o plano, tudo volta ao normal e depois piora de novo. - Fontes: - [Query Processing Architecture Guide](https://learn.microsoft.com/en-us/sql/relational-databases/query-processing-architecture-guide) · Microsoft SQL Server · Parameter sniffing: o plano de execução é montado de acordo com os valores de parâmetro recebidos na compilação ou recompilação - [Parameter Sensitive Plan Optimization](https://learn.microsoft.com/en-us/sql/relational-databases/performance/parameter-sensitive-plan-optimization) · Microsoft SQL Server · Com distribuição de dados desigual, um único plano em cache não serve para todos os valores de parâmetro - [Monitor performance by using the Query Store](https://learn.microsoft.com/en-us/sql/relational-databases/performance/monitoring-performance-by-using-the-query-store) · Microsoft SQL Server · Mudanças em estatísticas, schema ou índices alteram o plano, e o cache de planos guarda só o mais recente; forçar um plano no Query Store fixa o plano bom, e a tela de consultas regredidas (Regressed Queries) compara as queries que ficaram lentas e seus planos - [Statement Summary Tables](https://dev.mysql.com/doc/refman/8.4/en/performance-schema-statement-summary-tables.html) · MySQL · events_statements_summary_by_digest: COUNT_STAR e AVG_TIMER_WAIT (tempo médio) por formato de query - [pg_stat_statements — track statistics of SQL planning and execution](https://www.postgresql.org/docs/current/pgstatstatements.html) · PostgreSQL · calls, total_exec_time e mean_exec_time (tempo médio de execução) por comando - [pg_stat_statements (PostgreSQL 12 Documentation)](https://www.postgresql.org/docs/12/pgstatstatements.html) · PostgreSQL · Até a 12, as colunas se chamavam total_time e mean_time - [auto_explain — log execution plans of slow queries](https://www.postgresql.org/docs/current/auto-explain.html) · PostgreSQL · Registra no log o plano de execução das queries que levaram mais que auto_explain.log_min_duration #### db-ddl-lock · Lock de alteração de schema (DDL) em produção · Schema change lock (DDL / metadata lock) Adicionar uma coluna ou um índice a uma tabela com o jogo no ar exige um lock por um instante, e só esse lock pode deixar esperando todas as requisições que usam a tabela. - Por quê → Efeito → Na tela: Um hotfix adiciona coluna ou índice a uma tabela em produção → A alteração de schema espera uma transação longa aberta antes dela, e todas as requisições seguintes esperam a alteração de schema → Os recursos que usam essa tabela (inventário, correio etc.) param por inteiro e dão timeout - Sintomas: Input lag, Ação perdida / rollback, Não conecta / loading infinito / Fatores: Paralisação - Quem: Só um recurso específico, Servidor inteiro / Quando: Aleatoriamente, de vez em quando, Logo após login ou manutenção - Responsável principal: Infraestrutura de banco de dados (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Combinar com a infraestrutura de banco de dados o horário dos hotfixes que alteram o schema, fazer primeiro o deploy de um código que funcione mesmo sem a coluna nova. - O que fazer (Equipe de infraestrutura): Definir um limite curto de espera por lock e tentar de novo se falhar, executar quando não houver transações longas, usar ferramentas de alteração online, deixar tabelas grandes para a janela de manutenção. - No gráfico: Degrau a partir de um momento (Sessões esperando lock, latência das queries daquela tabela) - Onde olhar: No MySQL, contar no SHOW PROCESSLIST as sessões com State Waiting for table metadata lock e achar a sessão que está bloqueando (blocking_pid) com sys.schema_table_lock_waits. No PostgreSQL, ver no pg_locks as requisições com granted em false e os AccessExclusiveLock, e achar a sessão que está bloqueando com pg_blocking_pids() - Confirma se: A partir do horário em que a alteração de schema começou, todas as queries que usam aquela tabela se acumulam esperando lock, e na frente da fila há uma transação não terminada ou o próprio comando de alteração de schema - Descarta se: Espera concentrada em linhas específicas, com as outras linhas da mesma tabela processadas normalmente: hot row (db-hot-row) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Ao alterar o schema, o MySQL segura por um instante um metadata lock, e o PostgreSQL, o lock de tabela mais forte. Mesmo que a alteração em si seja instantânea, se houver na frente uma transação que ainda não terminou, todas as requisições seguintes ficam esperando. - Fontes: - [Online DDL Performance and Concurrency](https://dev.mysql.com/doc/refman/8.4/en/innodb-online-ddl-performance.html) · MySQL · Mesmo o DDL online precisa de um metadata lock exclusivo por um instante no final; se houver uma transação longa, ele espera, e o pedido de lock em espera bloqueia todas as transações seguintes - [Server System Variables](https://dev.mysql.com/doc/refman/8.4/en/server-system-variables.html) · MySQL · lock_wait_timeout: limite de espera por metadata lock, padrão de 31.536.000 segundos (1 ano) - [ALTER TABLE (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/sql-altertable.html) · PostgreSQL · ALTER TABLE sem especificação em contrário pega o lock mais forte, ACCESS EXCLUSIVE - [Client Connection Defaults (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/runtime-config-client.html) · PostgreSQL · lock_timeout: interrompe o comando se a espera pelo lock passar desse tempo - [General Thread States](https://dev.mysql.com/doc/refman/8.4/en/general-thread-states.html) · MySQL · Waiting for table metadata lock: estado da thread que espera um metadata lock - [The schema_table_lock_waits and x$schema_table_lock_waits Views](https://dev.mysql.com/doc/refman/8.4/en/sys-schema-table-lock-waits.html) · MySQL · Sessão que espera o metadata lock (waiting_query) e sessão que está bloqueando (blocking_pid) - [pg_locks (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/view-pg-locks.html) · PostgreSQL · granted em false indica espera pelo lock; mode mostra o tipo de lock, como AccessExclusiveLock - [System Information Functions and Operators (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/functions-info.html) · PostgreSQL · pg_blocking_pids(): lista das sessões que impedem a sessão indicada de obter o lock ### L13 Arquitetura e operação de servidores (13 causas) #### in-gateway · Tráfego via gateway ou proxy · Gateway / proxy hop Quando há um servidor intermediário entre o cliente e o servidor do jogo, cada passagem por ele soma tempo de processamento, e esse servidor vira um ponto único de falha. - Por quê → Efeito → Na tela: Arquitetura cliente ↔ gateway ↔ servidor do jogo → Processamento e espera extras no servidor intermediário, e a sobrecarga dele afeta todos → Ping mais alto para todos e, se o gateway cair, desconexão de todos os jogadores que passam por ele - Sintomas: Input lag, Desconexão / Fatores: Latência, Paralisação - Quem: Servidor inteiro / Quando: Quando junta muita gente, Sempre - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: permitir aumentar o número de gateways, fazer o personagem continuar de onde estava ao reconectar por outro gateway quando um cair (reconexão de sessão). Cliente: reconectar automaticamente quando o gateway cair. - O que fazer (Equipe de infraestrutura): Escalar os gateways horizontalmente (adicionar máquinas), monitorar CPU, número de conexões e latência de processamento de cada gateway. - Números de referência: Dentro do mesmo data center, cada passagem normalmente leva menos de 1 ms. Com o gateway sobrecarregado, sobe para dezenas ou centenas de ms. - No gráfico: Sobe com a carga (Latência de processamento do gateway, CPU e conexões do gateway) - Onde olhar: CPU e número de conexões do gateway, Recv-Q dos sockets do gateway (ss, netstat) e diferença de latência antes e depois do gateway. Em chamadas HTTP ou gRPC que passam pela service mesh, comparar a métrica padrão do Istio istio_request_duration_milliseconds separando quem envia (reporter=source) e quem recebe (reporter=destination) - Confirma se: O tempo de processamento do servidor do jogo não muda, só a latência no trecho do gateway sobe, e nesse momento a CPU do gateway satura ou o Recv-Q acumula - Descarta se: Rotas que não passam pelo gateway (conexão direta, outro gateway) igualmente lentas: aponta para a conexão ou para o servidor do jogo - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Com uma service mesh (Istio, por exemplo), o proxy sidecar (Envoy) que fica ao lado de cada servidor acrescenta mais uma etapa. As requisições entre serviços passam pelo sidecar de quem envia e depois pelo sidecar de quem recebe, e quanto mais funções o proxy ganha, como coleta de logs e métricas, mais crescem o tempo de processamento e o tempo de espera. - Casos reais: riot-edge-2020 - Fontes: - [The Unique Architecture behind Amazon Games’ Seamless MMO New World](https://aws.amazon.com/blogs/gametech/the-unique-architecture-behind-amazon-games-seamless-mmo-new-world/) · AWS · No New World, o cliente se conecta a um de 4 servidores de entrada (REP) com endereço público e se comunica com os servidores de simulação (hubs) que ficam atrás deles - [Designs, Lessons and Advice from Building Large Distributed Systems](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Keynote do LADIS 2009 (Jeff Dean). Ida e volta dentro do mesmo data center: cerca de 0,5 ms - [Site Reliability Engineering, Chapter 22: Addressing Cascading Failures](https://sre.google/sre-book/addressing-cascading-failures/) · Google · Quando a fila cresce por sobrecarga, a espera chega a várias vezes o tempo de processamento (com processamento de 100 ms e fila de 10 vezes o número de threads, 1,1 s) - [Performance and Scalability](https://istio.io/latest/docs/ops/deployment/performance-and-scalability/) · Istio · No modo sidecar, a requisição passa pelo proxy sidecar de quem envia e depois pelo de quem recebe; quanto mais funções, mais longo o caminho de processamento dentro do proxy, e a coleta de telemetria aumenta a espera da requisição seguinte - [What is Envoy](https://www.envoyproxy.io/docs/envoy/latest/intro/what_is_envoy) · Envoy · O Envoy é um processo separado que roda ao lado de cada servidor de aplicação, e o app envia e recebe tudo pelo Envoy em localhost - [Istio Standard Metrics](https://istio.io/latest/docs/reference/config/metrics/) · Istio · istio_request_duration_milliseconds (distribuição do tempo de processamento de requisições HTTP e gRPC); o label reporter distingue o proxy de quem envia (source) e o de quem recebe (destination) - [netstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/netstat.8.html) · net-tools · Recv-Q: número de bytes em um socket conectado que o programa do usuário ainda não leu #### in-zone-transfer · Troca de mapa (transferência entre servidores) · Zone / server handoff Ao entrar em outro mapa ou dungeon, os dados do personagem passam para outro servidor, e esse processo gera atrasos e falhas. - Por quê → Efeito → Na tela: Entrar em dungeon ou mudar de continente troca o servidor responsável → Salvar → transferir → carregar; se o servidor de destino está lotado ou não há instância de dungeon livre, o jogador espera → Carregamento longo, falha ao entrar, desconexão durante a troca - Sintomas: Não conecta / loading infinito, Travamento, Desconexão, Rubber banding / Fatores: Latência, Paralisação - Quem: Só eu, Local ou canal específico / Quando: Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Reduzir os dados transferidos, reservar o servidor de destino com antecedência, voltar ao ponto de origem em caso de falha. - O que fazer (Equipe de infraestrutura): Monitorar a folga de instâncias livres nos servidores de dungeon e de zona, garantir máquinas suficientes antes do pico. - No gráfico: Sobe com a carga (Duração e número de falhas da troca de mapa) - Onde olhar: Tempo de cada etapa da transferência registrado pelo servidor (salvar, transferir, carregar) e motivos de falha, número de jogadores e de instâncias livres no servidor de destino - Confirma se: No horário dos reports de carregamento longo ou falha ao entrar, o tempo de transferência sobe ou as falhas se concentram, e o servidor de destino está lotado ou sem instâncias livres - Descarta se: Transferência rápida, mas trava depois de chegar: aponta para “Avalanche de spawns ao entrar em área lotada” ou para o carregamento no cliente - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Mesmo em um mundo seamless, sem telas de carregamento, o servidor responsável muda quando o personagem cruza a fronteira entre servidores. Perto da fronteira pode haver um engasgo ou rubber banding, com o personagem puxado para trás. - Fontes: - [The Unique Architecture behind Amazon Games’ Seamless MMO New World](https://aws.amazon.com/blogs/gametech/the-unique-architecture-behind-amazon-games-seamless-mmo-new-world/) · AWS · O mundo sem telas de carregamento é dividido em uma grade atendida por vários servidores (hubs), e o estado do jogador passa de hub para hub conforme ele se move; os modos por sessão pegam servidores livres de um pool compartilhado #### in-cascade · Falha em cascata · Cascading failure Quando um serviço fica lento, os servidores que o chamam ficam presos esperando a resposta, e até funções sem relação com ele param. - Por quê → Efeito → Na tela: Um serviço, como o BD ou a autenticação, fica lento → As threads e conexões dos servidores que o chamam ficam presas esperando, e os retries das requisições que falharam aumentam a carga → Até funções que parecem não ter relação ficam lentas ou param - Sintomas: Travamento, Input lag, Não conecta / loading infinito / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Quando junta muita gente, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Timeout em todas as chamadas, circuit breaker, isolamento por função (bulkhead), retries com intervalo crescente e número limitado, resposta do health check separada do trabalho pesado. - O que fazer (Equipe de infraestrutura): Dar folga no número de falhas e no intervalo do health check do load balancer para que um servidor lento por um instante não seja retirado na hora, limitar quantos servidores podem sair de uma vez. - No gráfico: Achata ao bater no limite (Tempo de resposta e taxa de erros por serviço, threads e conexões em uso) - Onde olhar: Tempo de resposta, taxa de erros e número de retries de cada serviço na mesma tela, com o eixo de tempo alinhado, para achar o primeiro que ficou lento. Atrás de um load balancer: tempo de resposta dos destinos (no AWS ALB, TargetResponseTime), número de 5xx dos destinos (HTTPCode_Target_5XX_Count) e número de destinos retirados por não estarem íntegros (UnHealthyHostCount) - Confirma se: A latência de um serviço sobe primeiro, depois as threads e conexões de quem o chama encostam no limite, os erros se espalham para outros serviços, e o número de retries e de destinos retirados sobe junto - Descarta se: Vários serviços ficaram lentos no mesmo instante: verificar primeiro falha em recurso compartilhado (BD, rede, host) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O health check (verificação de que o servidor está vivo) também amplia a cascata. Quando um servidor ocupado responde tarde à verificação, o load balancer retira um servidor que estava funcionando, o tráfego dele vai para os que sobraram, e o próximo servidor também começa a atrasar. - Casos reais: riot-edge-2020, riot-euw-2021, roblox-2021, aws-2021, aws-2025 - Fontes: - [Site Reliability Engineering, Chapter 22: Addressing Cascading Failures](https://sre.google/sre-book/addressing-cascading-failures/) · Google · Quando um servidor sobrecarregado falha no health check e sai, a carga se concentra nos que sobram e os retries aumentam a carga; recomenda-se limitar os retries, usar backoff exponencial com jitter e deadlines - [Circuit Breaker Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker) · Microsoft Azure · Requisições presas até o timeout ocupam threads e conexões com o BD e derrubam funções sem relação; quando as falhas se acumulam dentro de um tempo definido, as chamadas passam a ser recusadas na hora - [Timeouts, retries, and backoff with jitter](https://d1.awsstatic.com/builderslibrary/pdfs/timeouts-retries-and-backoff-with-jitter.pdf) · AWS · Amazon Builders' Library. Com 5 níveis de chamadas e 3 retries em cada nível, a carga no BD é multiplicada por 243; fazer retry em um só lugar e limitar com token bucket - [CloudWatch metrics for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html) · AWS · TargetResponseTime (tempo entre a requisição sair do load balancer e o destino começar a responder), HTTPCode_Target_5XX_Count (número de 5xx gerados pelos destinos), UnHealthyHostCount (número de destinos não íntegros) #### in-subservice · Falha em servidor auxiliar · Auxiliary service outage Quando falha um servidor que roda separado do servidor do jogo, como chat, party ou casa de leilões, só aquela função para de funcionar. - Por quê → Efeito → Na tela: O servidor dedicado a uma função fica lento ou cai → Só as requisições daquela função ficam sem resposta → Chat não funciona, convite de party sem resposta, mercado em loading infinito (o combate funciona normalmente) - Sintomas: Ação perdida / rollback, Não conecta / loading infinito / Fatores: Paralisação, Perda de pacotes - Quem: Só um recurso específico / Quando: Aleatoriamente, de vez em quando, Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Projetar para que o jogo continue mesmo com falhas, mostrar o estado de cada função, não concentrar várias funções em um único servidor central. - O que fazer (Equipe de infraestrutura): Health check e alertas para cada servidor auxiliar, redundância e reinício automático. - No gráfico: Queda de conexões em massa (Taxa de sucesso das requisições por função, conexões e health check dos servidores auxiliares) - Onde olhar: Health check, estado do processo e número de conexões de cada servidor auxiliar (chat, party, casa de leilões etc.), taxa de sucesso e tempo de resposta das requisições por função. Atrás de um load balancer, o UnHealthyHostCount do grupo de destino - Confirma se: Só o servidor da função reportada mostra falha no health check ou queda brusca de conexões, e o tick e o combate do servidor do jogo estão normais - Descarta se: Várias funções pararam juntas: aponta para o servidor central que intermedeia essas funções ou para falha em cascata - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Se um único servidor central (servidor de mundo ou gerenciador) intermedeia party, guilda, mensagens privadas e troca de servidor, várias funções param de uma vez quando esse servidor fica lento. - Fontes: - [Bulkhead Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead) · Microsoft Azure · Isolar os componentes em pools faz com que, se um falhar, os outros continuem funcionando e a falha não se espalhe - [REL05-BP01 Implement graceful degradation to transform applicable hard dependencies into soft dependencies](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_mitigate_interaction_failure_graceful_degradation.html) · AWS · AWS Well-Architected. Projetar para que as funções essenciais continuem operando com dados um pouco desatualizados ou alternativos mesmo com uma dependência fora do ar - [CloudWatch metrics for your Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html) · AWS · UnHealthyHostCount: número de destinos considerados não íntegros pelo health check #### in-deploy · Deploy e reinício · Deploy / rolling restart Quando os servidores são reiniciados para uma atualização sem transferir as conexões, os jogadores daquele servidor são desconectados, e os salvamentos logo antes do desligamento e as reconexões chegam todos de uma vez. - Por quê → Efeito → Na tela: Deploy de hotfix reinicia os servidores um por um → O servidor é desligado sem transferir as conexões para outro, e o salvamento de todos os jogadores dele cai de uma vez no BD → Desconexão sem aviso, avalanche de reconexões - Sintomas: Desconexão, Não conecta / loading infinito, Input lag / Fatores: Paralisação - Quem: Servidor inteiro, Local ou canal específico / Quando: Aleatoriamente, de vez em quando, Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Implementar drain (bloquear só as novas conexões e esperar os jogadores atuais saírem), transferir personagens para outro servidor, espalhar os salvamentos antes do desligamento, avisar que está pronto só depois de carregar o cache e terminar o aquecimento do JIT após o reinício, no hot reload ler os dados antes em outra thread e trocar tudo de uma vez entre dois ticks. - O que fazer (Equipe de infraestrutura): Fazer a ferramenta de deploy esperar o drain de cada servidor antes de reiniciá-lo, mandar tráfego ao servidor reiniciado só depois de confirmar que está pronto (aquecimento concluído), anunciar o horário do deploy. - Números de referência: Com 5.000 jogadores em um servidor, 5.000 salvamentos chegam ao BD nos poucos segundos antes do desligamento. - No gráfico: Queda de conexões em massa (Conexões por servidor, escritas no BD) - Onde olhar: Registro de execução da ferramenta de deploy (horário de reinício de cada servidor) sobreposto como linhas verticais (anotações) aos gráficos de conexões, desconexões, escritas no BD e requisições de login - Confirma se: As conexões caem bruscamente em um servidor de cada vez, no horário do reinício, com pico de escritas no BD logo antes e pico de requisições de login logo depois - Descarta se: Horário das quedas não coincide com o registro de deploy e reinício: aponta para crash do servidor ou para equipamento de rede - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Os primeiros minutos depois de religar também são lentos. O cache está vazio e as consultas ao BD se acumulam, e servidores em Java ou C# ainda não terminaram de otimizar o código durante a execução (aquecimento do JIT), então o mesmo trabalho leva mais tempo. Recarregar scripts e tabelas de dados sem desligar o servidor (hot reload) também deixa o tick parado durante a leitura e causa uma pausa curta. - Fontes: - [Site Reliability Engineering, Chapter 20: Load Balancing in the Datacenter](https://sre.google/sre-book/load-balancing-datacenter/) · Google · Ao receber SIGTERM, o servidor entra em estado lame duck, desvia as novas requisições para outros servidores e só termina as que estão em andamento; nos primeiros minutos após o reinício o JIT ainda não otimizou o código e o consumo de recursos é maior, então o servidor só recebe tráfego depois de aquecido - [Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/workloads/pods/probes/) · Kubernetes · A readiness probe segura o tráfego até terminar de abrir conexões, carregar arquivos e aquecer o cache - [Edit target group attributes for your Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/edit-target-group-attributes.html) · AWS · Ao cancelar o registro de um destino, novas conexões deixam de ser enviadas e as existentes passam por drain (padrão de 300 s) #### in-autoscale · Demora do autoscaling · Autoscaling lag Quando o número de jogadores dispara, novos servidores sobem automaticamente, mas a preparação leva alguns minutos, e nesse meio-tempo os servidores existentes ficam sobrecarregados. - Por quê → Efeito → Na tela: O começo de um evento faz as conexões dispararem → Alguns minutos até o novo servidor ligar e ficar pronto → Nos primeiros minutos após o início do evento, câmera lenta e jogadores que não conectam - Sintomas: Câmera lenta, Não conecta / loading infinito / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Quando junta muita gente, Logo após login ou manutenção - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Distribuir os jogadores entre canais (quem já está em um canal lotado não pode ser movido para o novo servidor), reduzir o tempo de inicialização e de carregamento de dados do novo servidor. - O que fazer (Equipe de infraestrutura): Escalar antes do evento, manter servidores reserva já aquecidos, ao reduzir só desligar depois que os jogadores restantes saírem. - Números de referência: De 1 a alguns minutos para detectar a carga (porque a métrica é uma média de alguns minutos), e mais alguns minutos para ligar o novo servidor, ler os dados do jogo e encher o cache. - No gráfico: Pico logo após abrir ou manutenção (Número de instâncias, uso de CPU, fila de login) - Onde olhar: Registro de atividades do autoscaling (quando decidiu escalar, quando a nova instância entrou em serviço) sobreposto aos gráficos de uso de CPU e de conexões. Na AWS, as métricas do grupo do Auto Scaling (só aparecem se ativadas) GroupDesiredCapacity (capacidade desejada), GroupPendingInstances (em preparação) e GroupInServiceInstances (em serviço) - Confirma se: Depois do pico de conexões, por alguns minutos só sobem a capacidade desejada e as instâncias em preparação, enquanto a CPU dos servidores existentes fica encostada no limite; a situação se normaliza quando as instâncias em serviço aumentam - Descarta se: Continua lento mesmo depois de as novas instâncias entrarem: aponta para causa fora do número de servidores (recurso compartilhado como o BD, falha em cascata) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O autoscaling é usado principalmente onde basta mandar jogadores novos para servidores novos, como login, gateway e dungeons. Reduzir também dá problema. Se, de madrugada, com menos gente, os servidores são desligados sem esperar os jogadores restantes saírem, esses jogadores são desconectados. - Casos reais: aws-2021, aws-2025 - Fontes: - [Target tracking scaling policies for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-scaling-target-tracking.html) · AWS · As métricas básicas do EC2 têm intervalo de 5 minutos (1 minuto com o monitoramento detalhado ativado); para reagir rápido, recomenda-se usar métricas com intervalo de 1 minuto ou menos - [Amazon CloudWatch metrics for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-metrics.html) · AWS · As métricas de grupo só são publicadas, a cada minuto, se forem ativadas: GroupDesiredCapacity (quantidade que o grupo tenta manter), GroupPendingInstances (instâncias que ainda não entraram em serviço) e GroupInServiceInstances (instâncias em serviço) - [Scheduled scaling for Amazon EC2 Auto Scaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-scheduled-scaling.html) · AWS · Aumenta e reduz a capacidade em horários definidos, antecipando mudanças de carga previsíveis - [Decrease latency for applications with long boot times using warm pools](https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-warm-pools.html) · AWS · Para apps que demoram a inicializar, um pool de instâncias pré-inicializadas (warm pool) reduz o atraso da escala #### in-monitoring · Sobrecarga de logs e monitoramento · Logging / monitoring overhead Quando há uma falha, o volume de logs explode, e servidores que enviam logs de forma síncrona ficam ainda mais lentos por causa deles. - Por quê → Efeito → Na tela: Os erros fazem explodir o volume de logs e métricas enviados → O coletor de logs fica para trás, e os servidores que enviam de forma síncrona ficam esperando → Engasgos e travamentos durante a falha pioram por causa dos logs - Sintomas: Engasgos, Travamento / Fatores: Paralisação - Quem: Servidor inteiro / Quando: Quando junta muita gente, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Envio assíncrono, amostragem, descartar quando o buffer encher, agrupar os logs do mesmo erro antes de enviar. - O que fazer (Equipe de infraestrutura): Dimensionar o coletor de logs pelo volume de pico durante falhas, alerta de acúmulo no coletor. - No gráfico: Picos aleatórios (Volume de logs enviados, fila do coletor de logs) - Onde olhar: Linhas e bytes de log por segundo no servidor, fila e descartes do agente de coleta de logs, junto com o tempo de tick. Se houver thread parada, verificar com bcc offcputime -p se ela espera na escrita ou no envio de logs - Confirma se: No momento do pico de tick, o volume de logs sobe para dezenas de vezes o normal, e o tempo de espera da thread do jogo se concentra nas pilhas de chamada de escrita e envio de logs - Descarta se: Volume de logs normal ou thread do jogo sem espera nos logs: a explosão de logs é só consequência da falha, então procurar à parte a causa do primeiro erro - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Logging in C#](https://learn.microsoft.com/en-us/dotnet/core/extensions/logging) · Microsoft · Os métodos de log do .NET são síncronos, então, se o destino é lento, recomenda-se escrever primeiro em um armazenamento rápido e mover depois - [Asynchronous loggers](https://logging.apache.org/log4j/2.x/manual/async.html) · Apache Software Foundation · O log assíncrono absorve picos curtos com uma fila, mas se a saída continua lenta a fila enche e a velocidade cai à da saída mais lenta, ou os logs são descartados conforme a política (Discard) - [Demonstrations of offcputime, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/offcputime_example.txt) · IO Visor · Soma, por pilha de chamadas, o tempo em que as threads ficaram paradas fora da CPU (off-CPU); -p especifica o processo #### in-clock-skew · Diferença de relógio entre servidores · Clock skew between servers Quando cada servidor tem o relógio um pouco diferente, as decisões sobre cooldown, buffs e início de eventos divergem de um servidor para outro. - Por quê → Efeito → Na tela: Em um servidor cuja sincronização de horário parou, o relógio se afasta dos outros servidores de centenas de ms a alguns segundos → Passar horários absolutos entre servidores, como o horário em que um buff acaba, faz as decisões divergirem → Depois de trocar de mapa, o buff some ou o cooldown recomeça - Sintomas: Ação perdida / rollback / Fatores: Latência - Quem: Só eu / Quando: Em movimento ou ao trocar de mapa - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Entre servidores, enviar o tempo restante, sem usar horários absolutos. - O que fazer (Equipe de infraestrutura): Monitorar a sincronização de horário (NTP, chrony), alerta de diferença de relógio entre servidores. - Números de referência: Com a sincronização de horário (NTP, chrony) funcionando, servidores do mesmo data center normalmente ficam a poucos ms uns dos outros. Se a sincronização para ou uma máquina virtual fica pausada por muito tempo e depois volta, a diferença chega a centenas de ms ou alguns segundos. - No gráfico: Subida lenta (Offset do relógio por servidor) - Onde olhar: Coletar e comparar, em cada servidor, System time (diferença entre o relógio do sistema e o relógio do NTP), Last offset e Ref time (último momento em que uma medição da fonte de tempo foi aplicada) do chronyc tracking - Confirma se: O offset do servidor com problema difere do dos outros em centenas de ms ou mais, ou o Ref time parou há muito tempo, e as decisões divergentes só aparecem em trocas de mapa que passam por esse servidor - Descarta se: Offset de todos os servidores dentro de alguns ms: aponta para o cálculo de tempo no jogo ou para erro na sincronização do relógio do cliente - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O relógio de um servidor pular de uma vez para frente ou para trás é tratado em “Salto do relógio do sistema (step do NTP)”, na camada SO do servidor (kernel). - Fontes: - [RFC 5905: Network Time Protocol Version 4: Protocol and Algorithms Specification](https://www.rfc-editor.org/rfc/rfc5905) · IETF · Em uma LAN rápida, clientes NTP normalmente ficam sincronizados dentro de centenas de µs - [chrony – Frequently Asked Questions](https://chrony-project.org/faq.html) · chrony · O drift de relógios de computadores comuns fica abaixo de 100 ppm, mas em máquinas virtuais pode ser maior; uma VM pausada e retomada pode ficar com o horário errado e precisar de correção por step - [clock_gettime(2) — Linux manual page](https://man7.org/linux/man-pages/man2/clock_gettime.2.html) · Linux man-pages · CLOCK_REALTIME pode dar saltos descontínuos por mudanças manuais e correções do NTP, e CLOCK_MONOTONIC não é afetado por esses saltos - [chronyc(1)](https://chrony-project.org/doc/4.6/chronyc.html) · chrony · chronyc tracking: System time (diferença entre o relógio do NTP e o relógio do sistema), Last offset (offset estimado na última correção), Ref time (momento em que a última medição da fonte de tempo foi aplicada) #### in-bots · Excesso de macros e bots · Bots and macros Bots mandam requisições com muito mais frequência que pessoas e consomem a capacidade de processamento do servidor. - Por quê → Efeito → Na tela: Muitos bots conectados repetindo sem parar caça, movimento e trocas → Mais processamento no servidor e mais carga no BD → Uma área de caça ou o servidor inteiro fica lento (câmera lenta, input lag) - Sintomas: Câmera lenta, Input lag / Fatores: Paralisação - Quem: Servidor inteiro, Local ou canal específico / Quando: Sempre, Horário de pico à noite - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Detectar bots, limitar a frequência de requisições por conta e por personagem. - O que fazer (Equipe de infraestrutura): Limitar a frequência de conexões e requisições por IP (com folga para lan houses e redes móveis, onde várias pessoas usam o mesmo IP), bloquear faixas de bots no firewall ou WAF. - No gráfico: Alto só em alguns (Requisições por segundo por conta e por IP) - Onde olhar: Distribuição e ranking de requisições por segundo por conta e por personagem nos logs do servidor do jogo. Sem métricas no código, número de requisições por IP no firewall ou WAF - Confirma se: Poucas contas ou IPs fazem requisições sem parar, em uma frequência impossível para uma pessoa, e limitá-los reduz a carga do servidor de forma visível - Descarta se: Requisições distribuídas por igual entre as contas: aponta para aumento normal de jogadores (estouro do tick, demora do autoscaling) - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Using rate-based rule statements in AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-rate-based.html) · AWS · Conta as requisições por critério, como IP, e limita a taxa quando passam do máximo dentro de uma janela de tempo definida - [RFC 6269: Issues with IP Address Sharing](https://www.rfc-editor.org/rfc/rfc6269) · IETF · Quando vários assinantes compartilham um IP, bloqueios e limites por IP atingem também outros usuários #### in-external · Dependência de serviços externos · External dependencies (auth, billing, platform) Quando um serviço externo, como login da plataforma, pagamento ou verificação de identidade, fica lento ou para, o jogador fica preso nessa etapa. - Por quê → Efeito → Na tela: Falha ou lentidão no serviço externo de autenticação ou pagamento → Espera pela resposta nessa etapa → Não consegue fazer login, pagamento falha. Quem já está jogando não é afetado - Sintomas: Não conecta / loading infinito, Ação perdida / rollback / Fatores: Paralisação - Quem: Servidor inteiro, Só um recurso específico / Quando: Logo após login ou manutenção, Ao fazer ações específicas - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Timeout e mensagem clara nas chamadas externas, cache do resultado da autenticação, retry e procedimento de compensação para pagamentos. - O que fazer (Externo): Pedir aos provedores de autenticação, pagamento e plataforma que confirmem a falha e restabeleçam o serviço, avisar os jogadores de que a falha está em um serviço externo. - No gráfico: Degrau a partir de um momento (Tempo de resposta e taxa de erros das chamadas externas, logins bem-sucedidos) - Onde olhar: Tempo de resposta, taxa de erros e número de timeouts de cada chamada externa (login da plataforma, pagamento, verificação de identidade) e a página de status do provedor - Confirma se: A partir do horário em que as falhas de login e pagamento se concentram, só os erros e timeouts de uma chamada externa sobem um degrau e ficam lá, e a página de status do provedor mostra falha no mesmo horário - Descarta se: Chamadas externas normais, mas login bloqueado: aponta para o próprio servidor de login (esgotamento do pool de threads, BD) ou para a fila de conexões do sistema operacional (backlog) - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Casos reais: fastly-2021, aws-2021, aws-2025 - Fontes: - [Timeouts, retries, and backoff with jitter](https://d1.awsstatic.com/builderslibrary/pdfs/timeouts-retries-and-backoff-with-jitter.pdf) · AWS · Amazon Builders' Library. Enquanto espera a resposta, a chamada ocupa recursos como threads e conexões, por isso usar timeout e só fazer retry de APIs com efeitos colaterais quando a idempotência estiver garantida - [Circuit Breaker Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker) · Microsoft Azure · Chamadas com alta chance de falhar são recusadas na hora, sem esperar o timeout, para manter o tempo de resposta - [REL05-BP01 Implement graceful degradation to transform applicable hard dependencies into soft dependencies](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_mitigate_interaction_failure_graceful_degradation.html) · AWS · AWS Well-Architected. Mesmo com um serviço dependente fora do ar, manter as funções essenciais, ainda que com dados um pouco desatualizados (base para o cache do resultado da autenticação) #### in-region-match · Erro de matchmaking ou de atribuição de região · Wrong region assignment (matchmaking / GeoDNS) Quando o jogador é mandado para um servidor de uma região distante, mesmo havendo uma região próxima, só o ping dele fica sempre alto, ainda que a conexão esteja boa. - Por quê → Efeito → Na tela: Erro nos dados de GeoIP, VPN, party inteira atribuída pela média de ping dos membros, regra que amplia a busca para regiões distantes quando faltam jogadores, atribuição pela localização do resolvedor DNS → Conexão a um servidor em uma região do outro lado do oceano, mesmo havendo uma região próxima → Em jogos com servidores em várias regiões, só você (ou só a sua party) tem ping sempre alto, com input lag, rubber banding e skills que não saem - Sintomas: Input lag, Rubber banding, Ação perdida / rollback / Fatores: Latência - Quem: Só eu, Região ou operadora específica / Quando: Sempre, Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Infraestrutura de rede (Equipe de infraestrutura), Externo (Externo) - O que fazer (Equipe de desenvolvimento): Servidor: atribuir pela latência que o cliente mediu para cada região no lugar do GeoIP, colocar um teto de ping na regra que amplia para regiões distantes, considerar o ping mais alto da party além da média, registrar em log a região atribuída e o ping no momento. Cliente: medir o ping de cada região por UDP e enviar junto com o pedido de matchmaking, mostrar na tela a região conectada e o ping, oferecer a opção de escolher a região manualmente. - O que fazer (Equipe de infraestrutura): Se a região é escolhida por DNS, verificar se o DNS autoritativo suporta EDNS Client Subnet (se o resolvedor do jogador não enviar, a atribuição segue a localização do resolvedor), atualizar o banco de dados de GeoIP periodicamente, anexar país e ASN do GeoIP aos logs de conexão dos servidores de cada região para achar países e operadoras que vão para regiões distantes. - O que fazer (Externo): Orientar os jogadores a desligar VPN e redutor de ping e conectar de novo, orientar quem usa DNS corporativo ou do exterior a trocar para o DNS da operadora, pedir ao provedor de GeoIP a correção de localizações erradas. - Números de referência: Um jogador de Seul atribuído à região Oeste dos EUA no lugar de Tóquio vê o ping subir de cerca de 30 ms para cerca de 130 ms. O GeoIP acerta cerca de 99,8% no nível de país, mas no nível de cidade, mesmo nos EUA, só cerca de 66% ficam dentro de 50 km, e com VPN aparece a localização do servidor VPN no lugar da do jogador. - No gráfico: Alto só em alguns (RTT (ping) por jogador, distribuição das regiões atribuídas) - Onde olhar: Anexar país e ASN do GeoIP aos IPs de clientes nos registros de conexão dos servidores de cada região (logs de acesso do load balancer, VPC Flow Logs) e contar para qual região cada país e operadora se conectou. Para um único jogador, comparar a região em que ele realmente se conectou com o ping até a região próxima (medido pelo jogador ou com mtr do servidor dessa região para o IP dele) - Confirma se: Jogadores e países com RTT alto estão conectados a uma região distante, havendo uma próxima, e o ping medido até a região próxima é baixo - Descarta se: Atribuído corretamente à região próxima e ainda assim com ping alto: aponta para roteamento com desvio ou para a conexão ou o Wi-Fi desse jogador - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: A escolha de região por DNS (DNS por geolocalização ou por latência) estima a localização do jogador pelo endereço do resolvedor DNS que ele usa. Se o resolvedor não suporta EDNS Client Subnet, que repassa parte do endereço do jogador, quem usa DNS corporativo ou um DNS distante é atribuído pela localização do resolvedor. O sistema de matchmaking também pode avaliar a party pela média de ping dos membros ou, depois de muita espera, ampliar o critério de ping e mandar o grupo para uma região distante. No AWS GameLift Servers, o critério padrão de ping da party também é a média, e a documentação dá como exemplo uma configuração que amplia o teto de ping de 50 ms para 100 ms e depois 200 ms. Para quem usa VPN, a latência extra do servidor intermediário (“Tráfego via VPN ou redutor de ping”) pode se somar à atribuição a uma região distante; para separar as duas coisas, veja se a região atribuída muda ao desligar a VPN e conectar de novo. Quando não existe região próxima e a conexão vai para uma distante, o assunto é tratado em “Atraso de propagação (distância física)”. - Fontes: - [RFC 7871: Client Subnet in DNS Queries](https://www.rfc-editor.org/rfc/rfc7871) · IETF · DNS que responde de acordo com a localização estima a posição pelo endereço do resolvedor que enviou a consulta, e quem usa um resolvedor central distante recebe respostas inadequadas. O EDNS Client Subnet (opcional) repassa parte do endereço do usuário - [How Amazon Route 53 uses EDNS0 to estimate the location of a user](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy-edns0.html) · AWS · Se o resolvedor não suporta edns-client-subnet, a localização do usuário é estimada pelo endereço do resolvedor, e a resposta segue a localização dele (vale para roteamento por geolocalização e por latência) - [Geolocation accuracy](https://support.maxmind.com/knowledge-base/articles/maxmind-geolocation-accuracy) · MaxMind · Cerca de 99,8% no nível de país, cerca de 66% no nível de cidade nos EUA (dentro de 50 km); com VPN, aparece a localização do servidor VPN no lugar da do usuário final; IPs de rede móvel são usados em áreas amplas e não dão localização precisa; o banco de dados precisa de atualização contínua; aceita pedidos de correção - [FlexMatch rule types](https://docs.aws.amazon.com/gameliftservers/latest/flexmatchguide/match-rules-reference-ruletype.html) · AWS · A regra de latência (maxLatency) olha a latência dos jogadores em cada local, a party usa por padrão a média dos membros (partyAggregation avg), e a fila pode alocar em regiões que não atendem à regra de latência - [Create a player latency policy](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/queues-design-latency.html) · AWS · Aloca no local com a menor latência média entre todos os jogadores, mas jogadores com latência extrema também são alocados; exemplo de política que amplia o teto de ping de 50 ms para 100 ms e depois 200 ms - [Amazon GameLift Servers UDP ping beacons](https://docs.aws.amazon.com/gameliftservers/latest/developerguide/reference-udp-ping-beacons.html) · AWS · O cliente do jogo mede a latência com endpoints UDP presentes em cada local de hospedagem e usa o resultado na alocação e no matchmaking; é mais próximo do tráfego real do jogo que o ping ICMP - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Mediana medida de ida e volta a partir de Seul (Korea Central): Tóquio (Japan East) 29 ms, Oeste dos EUA 124–136 ms - [Flow log records](https://docs.aws.amazon.com/vpc/latest/userguide/flow-log-records.html) · AWS · srcaddr em registros de VPC Flow Logs: no tráfego de entrada, endereço IP de quem enviou #### in-cert · Certificado TLS expirado ou mal configurado · TLS certificate expiry / misconfiguration Quando o certificado do servidor de login, de API ou de patch expira, ou falta o certificado intermediário, a conexão TLS dos clientes que se conectam a partir desse momento falha. - Por quê → Efeito → Na tela: Certificado com validade vencida, servidor que envia a cadeia sem o certificado intermediário, ou data e hora erradas no dispositivo do jogador → O cliente falha na validação do certificado e encerra a conexão TLS → Não conecta ou fica em loading infinito no login ou no patch, ou só as funções em HTTPS, como a loja, falham. Quem já estava conectado em geral não é afetado - Sintomas: Não conecta / loading infinito, Ação perdida / rollback / Fatores: Paralisação - Quem: Servidor inteiro, Só um recurso específico, Só eu / Quando: Logo após login ou manutenção, Ao fazer ações específicas - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Registrar erros de certificado com um código de erro separado das outras falhas de conexão e orientar o jogador, em erro de data orientar o jogador a ativar o ajuste automático de data e hora do dispositivo, se usar pinning de certificado incluir chaves reserva e alinhar o calendário de troca de certificados com a equipe de infraestrutura. - O que fazer (Equipe de infraestrutura): Rede: quando o TLS termina no load balancer ou na CDN, alertar sobre o estado da renovação automática dos certificados gerenciados e os dias restantes (no ACM, DaysToExpiry), manter os registros DNS de validação. Servidores/SO: quando o TLS termina no servidor, automatizar a renovação e recarregar a configuração depois dela, configurar a cadeia incluindo o certificado intermediário, verificar periodicamente, de fora, a validade restante de cada endereço de login, API e patch, com alerta. - Números de referência: Os certificados da Let’s Encrypt valem 90 dias e a recomendação é renovar a cada 60 dias; o AWS Certificate Manager verifica certificados validados por DNS 45 dias antes de expirarem e renova automaticamente. Se a renovação automática falha em silêncio, as novas conexões são bloqueadas todas de uma vez, exatamente no horário da expiração. - No gráfico: Queda de conexões em massa (Logins bem-sucedidos, erros de handshake TLS) - Onde olhar: Ver com openssl s_client -connect HOST:443 -showcerts a lista de certificados que o servidor realmente envia e conferir a data de expiração (notAfter) de cada um com openssl x509 -noout -enddate. Se o TLS termina no load balancer, número de erros de negociação TLS (no AWS ALB e NLB, ClientTLSNegotiationErrorCount) e de logins bem-sucedidos - Confirma se: A data de expiração já passou ou falta o certificado intermediário na lista enviada pelo servidor, e o início dos erros coincide com o horário de expiração ou de troca do certificado - Descarta se: Lista de certificados e datas de expiração normais, mas só alguns jogadores falham: verificar a data e hora do dispositivo deles ou a lista de certificados raiz de um SO antigo - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Uma configuração sem o certificado intermediário pode parecer normal quando aberta no navegador do PC. O navegador lembra certificados intermediários recebidos de outros sites e preenche a lacuna, mas clientes sem essa memória, como apps Android, falham. A validade também está encurtando. A Let’s Encrypt pretende reduzir a validade padrão para 64 dias em 2027 e 45 dias em 2028; uma configuração fixa de renovação a cada 60 dias terá só quatro dias de folga com certificados de 64 dias e passará da expiração com os de 45 dias. O AWS Certificate Manager também não renova automaticamente certificados importados, e a renovação falha se o registro DNS de validação for apagado. O login bloqueado se parece com “Falha ou lentidão no DNS”, mas no problema de certificado a falha acontece no handshake TLS, depois de o endereço do servidor ser encontrado, e o início coincide com o horário de expiração ou de troca do certificado. - Fontes: - [RFC 5280: Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile](https://www.rfc-editor.org/rfc/rfc5280) · IETF · A validade do certificado vai de notBefore a notAfter, e a validação do caminho confere, para cada certificado da cadeia, se o horário atual está dentro da validade (falha se o relógio de quem valida estiver errado) - [FAQ](https://letsencrypt.org/docs/faq/) · Let's Encrypt · Validade padrão do certificado de 90 dias, renovação recomendada a cada 60 dias - [Decreasing Certificate Lifetimes to 45 Days](https://letsencrypt.org/2025/12/02/from-90-to-45) · Let's Encrypt · Reduz a validade padrão para 64 dias a partir de fevereiro de 2027 e 45 dias a partir de fevereiro de 2028; renovar em intervalo fixo de 60 dias deixa de bastar, e a recomendação passa a ser renovar por volta de dois terços da validade - [Renewal for domains validated by DNS](https://docs.aws.amazon.com/acm/latest/userguide/dns-renewal-validation.html) · AWS · 45 dias antes da expiração, verifica se o certificado está em uso em um serviço da AWS e se o registro CNAME de validação existe, e renova automaticamente; se não conseguir validar, avisa 30, 15, 7, 3 e 1 dia antes da expiração - [Managed certificate renewal in AWS Certificate Manager](https://docs.aws.amazon.com/acm/latest/userguide/managed-renewal.html) · AWS · Certificados importados e certificados já expirados não entram na renovação automática - [Supported CloudWatch metrics](https://docs.aws.amazon.com/acm/latest/userguide/cloudwatch-metrics.html) · AWS · DaysToExpiry: dias restantes até a expiração do certificado, publicada duas vezes por dia até expirar - [Security with network protocols](https://developer.android.com/privacy-and-security/security-ssl) · Android (Google) · Se o servidor envia a cadeia sem o certificado intermediário, apps Android falham com SSLHandshakeException, mas o navegador do PC pode completá-la com intermediários guardados e não dar erro; verificar com openssl s_client a cadeia que o servidor envia - [Network security configuration](https://developer.android.com/privacy-and-security/security-config) · Android (Google) · Com pinning de certificado, é preciso incluir chaves reserva para troca de chave ou de CA; sem isso, as conexões ficam bloqueadas até o app ser atualizado - [openssl-s_client](https://docs.openssl.org/3.0/man1/openssl-s_client/) · OpenSSL · -showcerts: mostra a lista de certificados enviada pelo servidor na ordem em que foi enviada (não é a cadeia validada) - [openssl-x509](https://docs.openssl.org/3.0/man1/openssl-x509/) · OpenSSL · -enddate: imprime a data de expiração do certificado (notAfter); -checkend: verifica se expira dentro do número de segundos informado - [CloudWatch metrics for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html) · AWS · ClientTLSNegotiationErrorCount: número de conexões que não conseguiram estabelecer a sessão TLS, como quando o cliente falha na validação do certificado do servidor e encerra a conexão - [CloudWatch metrics for your Network Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-cloudwatch-metrics.html) · AWS · ClientTLSNegotiationErrorCount: número de handshakes TLS em que a negociação entre o cliente e o listener TLS falhou #### in-login-queue · Limite da fila de login e pouca tolerância para reconexão · Login queue cap / no reconnect grace Quando as conexões se acumulam logo após um lançamento ou manutenção, a fila de login bate no limite e passa a recusar novas entradas, e quem estava esperando e cai por um instante perde a posição e volta para o fim da fila. - Por quê → Efeito → Na tela: Há mais gente tentando entrar do que o servidor de login aguenta de uma vez, então existe uma fila, e quando ela fica longa demais novas entradas são recusadas para proteger o servidor → Quanto mais longa a fila, maior a espera, e nesse tempo basta o Wi-Fi ou a rede móvel cair por um instante para perder a posição → Não conecta / loading infinito, o jogo fecha com erro durante a espera e o jogador volta para o fim da fila - Sintomas: Não conecta / loading infinito, Desconexão / Fatores: Paralisação - Quem: Servidor inteiro, Só eu / Quando: Logo após login ou manutenção, Horário de pico à noite - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Servidor: ajustar o limite da fila ao que o servidor de login realmente consegue processar, guardar por um tempo a posição de quem caiu durante a espera (tolerância para reconexão), mostrar a posição na fila e a espera estimada, registrar como métricas o tamanho da fila, as recusas e as quedas durante a espera. Cliente: se cair durante a espera, reconectar automaticamente à mesma posição sem fechar o jogo, espalhar os retries com backoff exponencial e jitter. - O que fazer (Equipe de infraestrutura): Servidores/SO: medir com teste de carga, antes do lançamento, o limite de processamento dos servidores de login e de lobby, deixar máquinas reserva prontas para adicionar no lançamento, ver as métricas da fila no mesmo gráfico das tentativas de conexão. - Números de referência: No lançamento da expansão de FINAL FANTASY XIV em 2021, cada data center lógico recusava novas entradas quando a fila passava de 17.000 pessoas (Error 2002). Se a conexão caía durante a espera, o servidor de lobby esperava de dezenas de segundos a 1 minuto, e quem reconectava nesse prazo continuava do meio da fila. - No gráfico: Achata ao bater no limite (Tamanho da fila de login, recusas por limite atingido, quedas durante a espera) - Onde olhar: Tamanho da fila, espera média, recusas por limite atingido e quedas durante a espera registrados pelos servidores de login e de lobby, no mesmo gráfico das tentativas de conexão - Confirma se: Logo após o lançamento ou a manutenção, enquanto o tamanho da fila bate no limite e fica achatado, as recusas sobem e as quedas durante a espera se concentram em jogadores de Wi-Fi e rede móvel - Descarta se: Fila curta, mas login lento: aponta para o BD (db-login-storm) ou para a fila de conexões do sistema operacional (so-backlog) - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Lentidão no BD por avalanche de logins é tratada em “Avalanche de logins e queries N+1”, e estouro da fila de conexões do sistema operacional, em “Estouro da fila de conexões (backlog)”. Este verbete trata do design da fila de login que o jogo cria de propósito. O limite da fila é uma proteção do servidor de login e não pode ser removido: recusar cedo as requisições excedentes é o que permite continuar processando as que dá para processar. O essencial é reduzir o prejuízo que recusas e quedas causam ao jogador, e quanto mais longa a fila, mais os erros se concentram em jogadores com conexão instável, como Wi-Fi e rede móvel. - Casos reais: ffxiv-2021 - Fontes: - [Response to Congestion (as of Dec. 11)](https://na.finalfantasyxiv.com/lodestone/news/detail/6a94b30182b6d963994fdc0b789264ac9f24986f) · Square Enix · Quando a fila passava de 17.000 pessoas em um data center lógico, novas entradas eram recusadas para o servidor de login não cair (Error 2002); quem caía durante a espera tinha de dezenas de segundos a 1 minuto de tolerância do servidor de lobby para voltar ao meio da fila, e depois disso voltava para o fim - [Using load shedding to avoid overload](https://aws.amazon.com/builders-library/using-load-shedding-to-avoid-overload/) · Amazon Builders' Library · Load shedding: recusar cedo as requisições excedentes para continuar processando as que dá para processar ### Design de sincronização (16 causas) #### sy-request-response · Feedback só depois da resposta do servidor (requisição-resposta) · Request-response (no client-side feedback) Ao apertar o botão, não há animação nem som até a resposta do servidor chegar. O ping vira o tempo de resposta. - Por quê → Efeito → Na tela: Skills, movimento e coleta de itens só são reproduzidos depois da confirmação do servidor → Desde o momento em que você aperta, nada acontece durante o tempo de ida e volta + a espera do tick → Com ping de 150 ms, todas as ações ficam 0,2 s mais lentas - Sintomas: Input lag / Fatores: Latência - Quem: Só eu / Quando: Sempre, Ao fazer ações específicas - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: começar animações, sons e efeitos assim que o jogador aperta (feedback no cliente), mostrar só os resultados (dano, recompensas) depois da confirmação do servidor, aplicar movimento e ataque básico na hora com predição e, ao receber uma correção de posição do servidor, reaplicar a partir dela os inputs ainda não confirmados. Servidor: calcular o movimento a partir dos inputs recebidos e enviar correção só quando a diferença para a posição prevista pelo cliente passar do limite. - Números de referência: Tempo de resposta ≈ ping + metade do intervalo entre ticks + um frame. Com 20 ticks e ping de 150 ms, cerca de 190 ms. - No gráfico: Sempre alto desde o início (Tempo do input até o início da animação, RTT (ping)) - Onde olhar: Registrar no log do cliente, em build de desenvolvimento, o horário do botão, do início da primeira animação ou som e da chegada da resposta do servidor, lado a lado com o RTT do jogo. Medir variando o ping com a emulação de rede da engine (Unreal NetEmulation.PktLag) ou com tc netem do Linux no servidor de testes - Confirma se: A animação sempre começa no mesmo instante em que a resposta do servidor chega, e o tempo do input até a animação é RTT + espera do tick, crescendo exatamente na medida do atraso inserido - Descarta se: A animação começa assim que o jogador aperta e só o resultado, como os números de dano, atrasa: design correto. Atraso maior que o intervalo entre ticks mesmo com ping baixo: aponta para espera dupla de tick ou problema de frame no cliente - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Para jogos que não precisam de resposta rápida, como os de turno, de cartas e idle, este modelo é o mais simples e seguro. O problema aparece quando um jogo com controle em tempo real usa esse modelo até para movimento e ataque básico. - Fontes: - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Um cliente que só espera o resultado do servidor mostra todas as ações 500 ms depois quando a latência é de 500 ms. A solução é predição no cliente e reconciliação com o servidor - [Using Gameplay Abilities in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-gameplay-abilities-in-unreal-engine) · Epic Games · Local Predicted executa assim que o jogador aperta e o servidor dá a decisão final; Server Initiated não tem predição, e quem usa vê o atraso - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · O cliente prevê e guarda os movimentos, só corrige quando o erro em relação ao servidor passa da tolerância (MAXPOSITIONERRORSQUARED) e, depois de corrigir, reaplica os movimentos guardados - [Using Network Emulation in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-network-emulation-in-unreal-engine) · Epic Games · Testa com latência mínima e máxima e taxa de perda de pacotes configuradas no servidor e no cliente; no console, a configuração usa comandos como NetEmulation.PktLag - [tc-netem(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-netem.8.html) · iproute2 · Ferramenta de teste que insere atraso e jitter (delay TIME JITTER) e perda (loss random PERCENT) nos pacotes de saída para imitar uma rede real #### sy-chatty · Protocolo com muitas idas e voltas em sequência (chatty) · Chatty protocol / sequential round trips Se uma única ação precisa de várias idas e voltas ao servidor, uma depois da outra, o ping é multiplicado por esse número. - Por quê → Efeito → Na tela: Abrir a loja → pedir a lista → conferir o preço → comprar → atualizar o inventário, cada etapa em uma requisição separada → A próxima requisição só sai depois que chega a resposta da anterior → Com ping de 150 ms, quase 1 segundo para comprar uma vez. Carregamentos estranhamente longos - Sintomas: Input lag, Não conecta / loading infinito / Fatores: Latência - Quem: Só um recurso específico, Só eu / Quando: Ao fazer ações específicas, Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: mudar o protocolo para agrupar várias etapas em uma só requisição e resposta (ex.: incluir o inventário atualizado na resposta da compra). Cliente: baixar antes os dados necessários, UI que não espera o resultado. - Números de referência: Tempo ≈ número de idas e voltas × (ping + processamento no servidor + espera do tick). Com 5 idas e voltas e ping de 150 ms, cerca de 0,85–1 s. - No gráfico: Sempre alto desde o início (Tempo de conclusão por função, idas e voltas por ação) - Onde olhar: Em uma captura de pacotes no servidor (Wireshark), contar quantas vezes requisições e respostas se alternam, e com que intervalo, enquanto uma conta de teste faz uma ação como comprar na loja ou fazer login. Com log de requisições no servidor, agrupar por ID de sessão e ver o número de requisições e o horário de chegada e de resposta de cada uma - Confirma se: Em uma única ação, as requisições esperam a resposta anterior e vão e voltam várias vezes em sequência, o tempo de conclusão é aproximadamente número de idas e voltas × RTT, e quanto maior o ping da região do jogador, mais lenta fica a mesma função, na mesma proporção - Descarta se: Uma ou duas idas e voltas, mas uma resposta demora: causa no processamento do servidor ou no BD. Todos os jogadores igualmente lentos, seja qual for o ping: verificar a carga do servidor - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Chatty I/O antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/chatty-io/) · Microsoft Azure · Muitas requisições de I/O pequenas acumulam atraso e derrubam a responsividade. Recomendação de agrupar em menos requisições, e maiores #### sy-no-queue · Sem buffer de comandos para skills · No input/spell queue Se a próxima skill só pode ser usada depois que o servidor confirma o fim da anterior, cada combo ganha um tempo de ida e volta no meio. - Por quê → Efeito → Na tela: O input da próxima skill só é aceito “depois da confirmação da skill anterior” → Entre uma skill e outra, fica um tempo vazio do tamanho do ping → Buracos entre as skills do combo, e quanto maior o ping, menor o DPS - Sintomas: Input lag, Ação perdida / rollback / Fatores: Latência - Quem: Só eu, Só um recurso específico / Quando: Ao fazer ações específicas - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: janela do buffer de comandos, que aceita o input feito dentro de um tempo antes do fim do cooldown (ex.: 0,3–0,4 s) e o envia na hora ao servidor. Servidor: executar no instante em que o cooldown termina o input que chegou um pouco cedo, sem rejeitá-lo. - Números de referência: Em um combo com cooldown de 1 s e ping de 150 ms, sobram pelo menos 0,15 s vazios entre as skills, e o número de skills usadas no mesmo tempo cai mais de 13%. - No gráfico: Sempre alto desde o início (Tempo vazio entre skills, RTT (ping)) - Onde olhar: Registrar no log do servidor, por personagem, o horário em que o cooldown da skill terminou, o horário de chegada da requisição da próxima skill e o horário de execução, e comparar o tempo vazio com o RTT do jogador - Confirma se: Entre o fim do cooldown e a execução da próxima skill sempre sobra cerca de um RTT, e quanto maior o ping do jogador, maior o tempo vazio e menos skills usadas no mesmo tempo - Descarta se: Tempo vazio constante, seja qual for o ping: design do cooldown global ou da duração das animações. Tempo vazio que só às vezes dá pico: verificar jitter, perda de pacotes ou estouro do tick - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: World of Warcraft, por exemplo, tem uma janela de buffer de comandos que o jogador pode ajustar nas configurações. Se a janela é maior que o tempo de ida e volta, o ping quase não aparece entre as skills do combo. - Fontes: - [Latency and Player Actions in Online Games (Communications of the ACM, 2006)](https://web.cs.wpi.edu/~claypool/papers/precision-deadline/final.pdf) · ACM · No EverQuest 2, quanto maior a latência, menos dano o personagem causa e mais longo fica o combate (de 0 para 500 ms, 5 s a mais em um combate de cerca de 2 minutos) #### sy-short-window · Janela de tempo curta consumida pelo ping · Timing window too short for latency + reaction Quando o tempo para reagir é curto, como em esquiva, parry ou defesa, o ping consome esse tempo e surgem ataques impossíveis de evitar. - Por quê → Efeito → Na tela: Janelas de tempo curtas, como um aviso de ataque do boss de 0,5 s ou uma janela de parry de 0,2 s → Você vê o aviso tarde (latência servidor → cliente + interpolação), e seu input também chega tarde (latência cliente → servidor + espera do tick) → Você desviou, mas levou o golpe; o parry não saiu - Sintomas: Ação perdida / rollback, Input lag / Fatores: Latência - Quem: Só eu, Só um recurso específico / Quando: Ao fazer ações específicas - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Servidor: agendar o aviso de ataque pelo horário do servidor e enviá-lo antes, alongar a janela de tempo na medida do ping (compensação de lag). Cliente: reproduzir o aviso recebido no horário agendado, pelo relógio do servidor. - O que fazer (Equipe de infraestrutura): Instalar servidores perto das regiões com mais jogadores (servidores regionais) para reduzir o próprio ping. - Números de referência: Com ping de 150 ms e interpolação de 100 ms, o aviso leva cerca de 0,18 s para aparecer na sua tela e seu input leva cerca de 0,1 s para chegar ao servidor. Somando a reação humana de 0,25 s, um aviso de 0,5 s fica quase impossível. - No gráfico: Alto só em alguns (Taxa de falha de esquiva e parry (por faixa de ping)) - Onde olhar: Registrar no log do servidor o início e o fim da janela de tempo, o horário de chegada do input do jogador ao servidor e o RTT dele, e separar a taxa de falha por faixa de ping (ex.: de 50 em 50 ms) - Confirma se: Quanto maior a faixa de ping, claramente maior a taxa de falha, e os inputs que falharam chegam um pouco depois do fim da janela (dentro de RTT + tempo de interpolação) - Descarta se: Taxa de falha parecida em todas as faixas de ping: problema de dificuldade do padrão de ataque. Input que chegou dentro da janela e ainda assim conta como falha: verificar o código de decisão ou a validação do servidor - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Factors influencing the latency of simple reaction time (Frontiers in Human Neuroscience, 2015)](https://doi.org/10.3389/fnhum.2015.00131) · Frontiers · Tempo de reação simples médio de cerca de 231 ms (213 ms corrigindo o atraso do equipamento); grandes estudos recentes ficam entre 233 e 400 ms - [Latency and Player Actions in Online Games (Communications of the ACM, 2006)](https://web.cs.wpi.edu/~claypool/papers/precision-deadline/final.pdf) · ACM · Quanto mais precisa a ação e mais curto o prazo, maior a sensibilidade à latência (limites em cerca de 100 ms na primeira pessoa, cerca de 500 ms na terceira pessoa e cerca de 1.000 ms na visão onisciente) - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Método que agenda eventos pelo horário do servidor (ServerTime) para que todos os clientes os reproduzam no mesmo instante #### sy-no-lagcomp · Registro de acerto sem compensação de lag · Server-now hit validation Se o servidor decide o acerto só pela “posição atual no servidor”, a decisão diverge do que você viu na tela. - Por quê → Efeito → Na tela: O adversário na sua tela está na posição de cerca de 0,2 s atrás (com ping de 150 ms e interpolação de 100 ms) → O servidor decide pela posição atual, e o alvo já não está onde você mirou → Você acertou, mas conta como erro. É preciso atirar à frente de alvos em movimento - Sintomas: Ação perdida / rollback / Fatores: Latência - Quem: Só eu / Quando: Ao fazer ações específicas - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: voltar no tempo até o momento que o atacante via e decidir ali (compensação de lag), ou mudar para seleção de alvo (tab target). Cliente: ao atacar, enviar junto o momento que estava vendo (o horário do servidor em interpolação). - No gráfico: Alto só em alguns (Taxa de acerto em alvos em movimento (por faixa de ping)) - Onde olhar: Registrar juntos no log de decisões do servidor o horário do ataque, a posição do alvo na tela do atacante (valor enviado pelo cliente), a posição do alvo no servidor usada na decisão e o RTT do atacante. Em build de desenvolvimento, desenhar sobre a tela do cliente a posição usada pelo servidor deixa isso visível na hora - Confirma se: Nas decisões de erro, a diferença entre as duas posições é aproximadamente velocidade do alvo × (RTT do atacante + tempo de interpolação), e quanto maior o ping, mais cai só a taxa de acerto em alvos em movimento - Descarta se: Erra até alvos parados: problema na hitbox ou na checagem de colisão. Diverge mesmo com volta no tempo: verificar se o cliente informa errado ao servidor o tempo de interpolação - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Sem compensação de lag, é preciso atirar à frente do alvo na medida da latência. Compensação de lag: o servidor volta no tempo o equivalente à latência mais o tempo de interpolação para decidir - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · O servidor volta ao estado do jogo que o jogador via no momento do tiro para decidir o acerto, e o cliente envia junto o horário da simulação que estava vendo - [Source SDK 2013: player_lagcompensation.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player_lagcompensation.cpp) · Valve · Na Source engine, tempo de volta = latência de rede + tempo de interpolação #### sy-lagcomp-overreach · Compensação de lag excessiva · Excessive lag compensation Se o servidor volta no tempo demais a favor do atacante, quem leva o tiro é atingido mesmo já tendo se escondido. - Por quê → Efeito → Na tela: O servidor volta muito no tempo para decidir a favor de um atacante com ping alto → Na tela de quem leva o tiro, ele já estava protegido → “Levei tiro atrás da parede”, quem tem ping alto leva vantagem - Sintomas: Ação perdida / rollback / Fatores: Latência - Quem: Só eu, Região ou operadora específica / Quando: Ao fazer ações específicas - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Definir um limite para a volta no tempo (ex.: 200–250 ms) e, para atacantes com ping acima disso, voltar só até o limite e deixar que compensem o resto atirando à frente. - No gráfico: Alto só em alguns (Tempo de volta por acerto (por ping do atacante)) - Onde olhar: Registrar no log de decisões do servidor, a cada acerto, o tempo de volta, o RTT do atacante e o horário do servidor em que o alvo entrou na cobertura. Em build de desenvolvimento, desenhar na tela a hitbox voltada no tempo (na Source engine, sv_showlagcompensation) - Confirma se: Os acertos dos reports de “levei tiro atrás da parede” se concentram em atacantes com tempo de volta longo, e o tempo de volta cresce com o ping do atacante, sem limite - Descarta se: Tiros atrás da parede mesmo em acertos com tempo de volta curto: problema na hitbox ou na checagem de colisão. Se o ping de quem leva o tiro é alto, o movimento dele chegou tarde ao servidor - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: A decisão com volta no tempo segue o princípio de “prioridade a quem atira”. Também foi proposta uma exceção de “prioridade a quem leva o tiro”, que não volta no tempo quando quem leva o tiro já entrou em lugar seguro na própria tela. - Fontes: - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Sem limite na volta no tempo, alguém com 500 ms de latência pode acertar 0,5 s depois de o alvo se proteger, por isso existe um limite - [A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022)](https://web.cs.wpi.edu/~claypool/papers/lag-taxonomy/paper.pdf) · ACM · Fenômeno do “tiro atrás da esquina (shot around the corner)”, limites de volta no tempo em FPS comerciais, proposta de técnica que não volta no tempo quando quem leva o tiro está seguro - [Source SDK 2013: player_lagcompensation.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player_lagcompensation.cpp) · Valve · Na Source engine, o limite de volta no tempo sv_maxunlag tem padrão de 1 s (máximo de 1 s), e sv_showlagcompensation mostra na tela a hitbox voltada no tempo #### sy-client-auth · Autoridade do cliente · Client-authoritative results Quando cada um decide o próprio resultado, sua tela fica fluida, mas os resultados divergem da tela dos outros e o jogo fica vulnerável a hacks. - Por quê → Efeito → Na tela: O cliente decide posição e acerto, e o servidor só repassa → Dois jogadores dizem que acertaram primeiro, e o servidor não tem como verificar → O adversário teleporta ou atravessa paredes, “eu acertei, mas não contou” - Sintomas: Teleporte, Ação perdida / rollback / Fatores: Latência - Quem: Servidor inteiro / Quando: Sempre - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: validar por conta própria os resultados importantes (acertos etc.), checar velocidade e distância no movimento. Cliente: ao receber um resultado rejeitado ou corrigido pelo servidor, voltar para esse valor. - No gráfico: Sempre alto desde o início (Reports de velocidade de movimento impossível e de acertos conflitantes) - Onde olhar: Gravar no servidor a posição e os acertos exatamente como o cliente reportou, calcular a velocidade de movimento pelos reports de posição consecutivos e contar os reports acima da velocidade máxima e os casos de dois jogadores dizendo que acertaram primeiro - Confirma se: O servidor repassa os reports a outros clientes sem validar, e velocidades impossíveis ou reports de acerto conflitantes aparecem de forma constante, seja qual for o patch ou a região - Descarta se: Se o servidor calcula ou valida os resultados por conta própria, a causa é outra. Nesse caso, para o teleporte, verificar perda de pacotes ou o buffer de interpolação - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Deixar o cliente reportar os resultados só funciona quando dá para confiar no cliente. Pelo risco de hacks, usa-se servidor autoritativo - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Modelo de autoridade do servidor: o servidor nunca confia no estado do jogo visto pelo cliente - [Distributed authority topologies (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/terms-concepts/distributed-authority.html) · Unity · Dividir a autoridade com os clientes facilita a trapaça e elimina a simulação única que governa todas as entidades #### sy-lockstep · Lockstep esperando o jogador mais lento · Lockstep waits for the slowest peer Em uma arquitetura em que todos calculam juntos o mesmo turno, se o input de um jogador atrasa, todos esperam. - Por quê → Efeito → Na tela: A cada turno, o cálculo só acontece quando chegam os inputs de todos os jogadores → O input de um jogador chega tarde por jitter ou perda de pacotes → Todos engasgam ao mesmo tempo e, nos casos graves, aparece a janela “Aguardando jogador” - Sintomas: Travamento, Engasgos, Input lag / Fatores: Jitter, Perda de pacotes, Paralisação - Quem: Local ou canal específico / Quando: Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: ajustar o atraso de input automaticamente de acordo com o ping, separar por um momento só quem está atrasado para que os outros sigam sem esperar. Cliente: aplicar o atraso de input definido; em P2P sem servidor intermediário, o cliente host também cuida do ajuste do atraso de input e do tratamento de quem atrasa. - Números de referência: Se o atraso de input for menor que “tempo para o input chegar ao outro jogador + jitter”, as paradas ficam frequentes. O tempo para chegar é metade do ping em conexão direta, e cerca de metade da soma do ping dos dois quando passa por um servidor intermediário. - No gráfico: Picos aleatórios (Tempo de espera por turno, atraso de chegada dos inputs por jogador) - Onde olhar: Registrar a cada turno o horário de chegada do input de cada jogador e o tempo em que o turno ficou parado esperando, e ver de quem era o input esperado nos turnos parados. Com servidor intermediário, também dá para ver pelo intervalo de chegada dos pacotes de input de cada jogador em uma captura de pacotes no servidor - Confirma se: Em todo turno parado, o input da mesma pessoa chegou depois do atraso de input, e nesse momento o jitter ou a perda de pacotes dessa pessoa dá pico - Descarta se: Todos os inputs chegaram a tempo e mesmo assim para: problema no tempo de cálculo do PC mais lento ou no processamento do servidor. Sem paradas, mas com resultados diferentes nas duas telas: divergência no resultado do cálculo (desync), então verificar “Divergência no cálculo de caminho na sincronização de comandos” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · O cálculo do frame n só acontece quando chegam todos os inputs, então, se algum atrasa, todos esperam. Com um buffer de atraso de reprodução pequeno para absorver o jitter, há engasgos - [1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond](https://www.gamedeveloper.com/programming/1500-archers-on-a-28-8-network-programming-in-age-of-empires-and-beyond) · Game Developer · Agenda os comandos para executar dois turnos depois e ajusta a duração do turno ao computador mais lento e ao ping (Speed Control) - [A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022)](https://web.cs.wpi.edu/~claypool/papers/lag-taxonomy/paper.pdf) · ACM · Define o atraso de input (incoming delay) igual à latência “A→servidor + servidor→B” para que todos apliquem o input no mesmo instante #### sy-rollback · Erro de predição no netcode de rollback · Rollback misprediction O jogo prevê o input do adversário e mostra o resultado antes; se errou, volta no tempo e recalcula. Quanto maior o ping, maior o trecho que precisa voltar. - Por quê → Efeito → Na tela: O adversário muda o input (diferente do previsto) → O input real chega meio ping atrasado, e o jogo volta esse tanto e recalcula → Os movimentos do adversário pulam alguns frames ou mudam de repente - Sintomas: Teleporte / Fatores: Latência, Jitter - Quem: Só eu / Quando: Ao fazer ações específicas, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Adicionar de 1 a 3 frames de atraso de input para reduzir quanto o jogo volta, definir um limite para a volta. - Números de referência: Com ping de 100 ms (50 ms em cada sentido), a 60 FPS o jogo volta cerca de 3 frames. Com 2 frames de atraso de input, cai para 1 frame. - No gráfico: Picos aleatórios (Frames voltados, RTT (ping)) - Onde olhar: Registrar no cliente, a cada rollback, quantos frames voltou, o RTT no momento, a configuração de atraso de input e o tempo gasto para voltar e recalcular - Confirma se: No instante em que o movimento do adversário pulou, o número de frames voltados é alto, e a volta média é aproximadamente (latência de um sentido − atraso de input) ÷ tempo de frame, crescendo com o ping - Descarta se: Volta pequena, mas com engasgos: problema de desempenho, o recálculo passa do tempo de um frame. Resultados que continuam diferentes nas duas telas depois da volta: divergência no resultado do cálculo (desync) - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [GGPO Rollback Networking SDK](https://www.ggpo.net/) · GGPO · Prevê o input do adversário e segue em frente; se o input real for diferente, recalcula do ponto da divergência até o presente - [8 Frames in 16ms: Rollback Networking in 'Mortal Kombat' and 'Injustice 2'](https://www.gdcvault.com/play/1025471/8-Frames-in-16ms-Rollback) · GDC · O rollback elimina o atraso de input local do lockstep, voltando e recalculando até 8 frames em 16 ms #### sy-no-timestamp · Eventos reproduzidos ao chegar, sem timestamp · Events played on arrival (no timestamps) Se o cliente reproduz os eventos do servidor assim que chegam, sem o horário em que aconteceram, o jitter da rede passa direto para o ritmo das animações e efeitos, que fica irregular. - Por quê → Efeito → Na tela: Eventos como “início do ataque” e “reproduzir efeito” executados assim que chegam → Cada pacote leva um tempo diferente para chegar, e o intervalo fica irregular → Animações de ataques em sequência ficam ora rápidas, ora lentas, e o timing dos padrões do boss muda a cada vez - Sintomas: Engasgos, Avanço rápido / Fatores: Jitter - Quem: Só eu / Quando: Sempre - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: reproduzir no horário que vem no evento (eventos agendados, buffer de interpolação). Servidor: enviar os eventos com o horário em que aconteceram (horário do servidor). - No gráfico: Picos aleatórios (Intervalo de reprodução dos eventos, intervalo de chegada dos pacotes) - Onde olhar: Casar, pelo número do evento, o horário em que o evento aconteceu no log do servidor com os horários de chegada e reprodução no log do cliente e comparar os intervalos. Reproduzir o problema em build de desenvolvimento inserindo jitter (valor de jitter do tc netem, latência mínima e máxima da emulação de rede do Unreal) - Confirma se: No servidor, os eventos acontecem em intervalos regulares, mas o intervalo de reprodução segue exatamente o intervalo de chegada e fica irregular - Descarta se: Chegada regular, mas reprodução irregular: problema de frame no cliente (picos de frame time). Intervalo já irregular no servidor: estouro do tick - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Cada atualização leva o horário do servidor, e o cliente desenha a posição no horário-alvo, que é o horário atual menos o tempo de interpolação (100 ms) - [Snapshot Interpolation](https://gafferongames.com/post/snapshot_interpolation/) · Gaffer On Games · Desenhar cada snapshot assim que chega dá engasgos por causa do jitter; acumular por um instante no buffer de interpolação antes de desenhar deixa tudo suave - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Exemplo em que o RPC leva o horário de envio e quem recebe reproduz o efeito no horário do servidor - [tc-netem(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-netem.8.html) · iproute2 · Ferramenta de teste que insere atraso e jitter (delay TIME JITTER) e perda (loss random PERCENT) nos pacotes de saída para imitar uma rede real - [Using Network Emulation in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-network-emulation-in-unreal-engine) · Epic Games · Testa com latência mínima e máxima e taxa de perda de pacotes configuradas no servidor e no cliente; no console, a configuração usa comandos como NetEmulation.PktLag #### sy-double-tick · Espera dupla de tick · Double tick quantization Se a requisição espera até o próximo tick para ser processada e o resultado também só sai no tick seguinte, o intervalo entre ticks se soma duas vezes. - Por quê → Efeito → Na tela: Requisições recebidas são processadas no próximo tick → O resultado também espera o próximo tick de envio para sair junto com os outros → Ping da conexão baixo, mas a resposta atrasa sempre cerca de 1,5 vez o intervalo entre ticks. Em um servidor de 10 ticks, 0,15 s em média e 0,2 s no pior caso - Sintomas: Input lag / Fatores: Latência - Quem: Servidor inteiro / Quando: Sempre - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Responder no mesmo tick em que a requisição foi processada, aumentar o tick rate, enviar na hora as respostas importantes. - Números de referência: Em um servidor de 10 ticks, cada tick dura 100 ms, então só a espera de tick soma 150 ms em média e 200 ms no pior caso. Esperando uma vez só, a média é de 50 ms. - No gráfico: Sempre alto desde o início (Tempo entre a chegada da requisição e o envio da resposta) - Onde olhar: Em uma captura de pacotes no servidor, medir o intervalo entre a chegada do pacote de requisição e a saída do pacote de resposta enquanto uma conta de teste repete a mesma ação (ex.: usar um item). Com logs no servidor, ver o horário de chegada da requisição, o número do tick que a processou e o horário de envio da resposta - Confirma se: O tempo dentro do servidor fica em cerca de 1,5 vez o intervalo entre ticks em média e 2 vezes no máximo, constante seja qual for o RTT - Descarta se: Tempo no servidor por volta de metade do intervalo entre ticks: há uma só espera de tick. Tempo maior que o intervalo entre ticks e irregular: verificar estouro do tick - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · O input que chega espera até um tick inteiro pela próxima fronteira de tick, e aplicar e enviar leva mais um frame. Quanto maior o tick rate, menor esse tempo - [VALORANT's 128-Tick Servers](https://www.riotgames.com/en/news/valorants-128-tick-servers) · Riot Games · Parte da latência vem da rede, e parte, do tick rate do servidor - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Mudanças em NetworkVariable não são enviadas na hora; são acumuladas e enviadas a cada tick de rede #### sy-strict-check · Validação rígida demais no servidor · Over-strict server validation Se o servidor checa com rigidez demais a velocidade de movimento, o cooldown e o alcance, rejeita até inputs normais que chegaram juntos por causa do jitter. - Por quê → Efeito → Na tela: Critérios rígidos como “distância máxima por tick” e “tolerância de 0 ms no cooldown” → Quando o jitter faz dois comandos chegarem no mesmo tick, o servidor considera violação da regra → Rubber banding, skill rejeitada mesmo com o cooldown pronto - Sintomas: Rubber banding, Ação perdida / rollback / Fatores: Jitter - Quem: Só eu / Quando: Aleatoriamente, de vez em quando, Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Checar por tolerância acumulada (token bucket), deixar folga do tamanho do ping e do jitter. - No gráfico: Picos aleatórios (Rejeições na validação do servidor e correções de posição) - Onde olhar: Registrar no log do servidor, a cada rejeição na validação ou correção de posição, o motivo, quantos comandos daquele jogador chegaram naquele tick e o intervalo de chegada desde o comando anterior - Confirma se: As rejeições e correções se concentram nos momentos em que 2 ou mais comandos chegaram no mesmo tick, e o deslocamento e o número de usos somados em janelas de alguns segundos ficam dentro da regra - Descarta se: Passa da regra mesmo somando em janelas de alguns segundos: possível excesso de velocidade real ou cheat. Rejeições concentradas em uma operadora e no horário da noite: aponta para “Falsos positivos da validação concentrados em uma operadora” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Source SDK 2013: player.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player.cpp) · Valve · Um orçamento de processamento de comandos que se acumula a cada tick (no máximo sv_maxusrcmdprocessticks, 24 ticks) permite comandos que chegam juntos. Comentário de desenvolvimento dizendo que bloquear com mais rigidez fazia jogadores normais também terem engasgos - [RFC 2697: A Single Rate Three Color Marker](https://www.rfc-editor.org/rfc/rfc2697) · IETF · Token bucket: decide pela taxa média (CIR) e pelo tamanho de burst permitido de uma vez (CBS) #### sy-host · Arquitetura com host (dono da sala) · Listen server / host advantage Quando o PC de um jogador faz o papel de servidor, a conexão e o desempenho do PC dele definem o que todos sentem. - Por quê → Efeito → Na tela: O PC do host faz o papel de servidor (P2P, listen server) → Conexão ou PC lento do host afeta todos, e o host joga com ping 0 → Só o host leva vantagem, e quando ele sai todos travam ou são desconectados - Sintomas: Engasgos, Travamento, Desconexão / Fatores: Latência, Paralisação - Quem: Local ou canal específico / Quando: Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento), Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Servidor: migrar para servidores dedicados que cuidem das decisões e, até lá, escolher como host no matchmaking quem tem conexão e PC melhores. Cliente: suportar migração de host, medir no matchmaking o ping até os outros participantes, a velocidade de upload e o desempenho do PC e enviar esses dados. - O que fazer (Equipe de infraestrutura): Garantir máquinas e instâncias para os servidores dedicados, instalá-los perto das regiões com mais jogadores. - No gráfico: Alto só em alguns (Reports de lag e desconexões por host) - Onde olhar: Registrar no log da partida a velocidade de upload do host, o RTT de cada participante até o host, o frame time do PC do host e o horário em que o host saiu, e agrupar os reports de lag e desconexão por host. Os próprios jogadores também podem confirmar jogando de novo com as mesmas pessoas e trocando só o host - Confirma se: Lag e desconexões se concentram nas salas de um host específico, todos os participantes pioram juntos quando o upload desse host está baixo ou o frame time dele está alto, e, sem migração de host, todos caem no instante em que o host sai - Descarta se: Só os participantes de uma região pioram, seja quem for o host: problema de conexão ou de rota. Com servidores dedicados, a causa é outra - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Networking Overview for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/networking-overview-for-unreal-engine) · Epic Games · O host do listen server leva vantagem sobre os outros clientes e tem carga maior, porque cuida do servidor e da renderização ao mesmo tempo - [Distributed authority topologies (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/terms-concepts/distributed-authority.html) · Unity · Quando o dono da sessão sai, um novo dono é eleito automaticamente entre os clientes restantes - [A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022)](https://web.cs.wpi.edu/~claypool/papers/lag-taxonomy/paper.pdf) · ACM · Até jogos P2P podem ser vistos como uma arquitetura cliente-servidor em que o host acumula o papel de servidor #### sy-optimistic-reject · Servidor rejeita o que o feedback no cliente já mostrou · Client-side feedback rejected by server Se o servidor não reconhece depois um golpe ou uma skill que sua tela já mostrou, o resultado que você viu claramente deixa de ter acontecido. - Por quê → Efeito → Na tela: Efeito de golpe e animação da skill reproduzidos antes da confirmação do servidor (feedback no cliente) → O servidor reavalia alcance, posição do alvo, cooldown e recursos e rejeita → Saiu sangue, mas não houve dano; a animação da skill saiu sem efeito, só o cooldown começou a correr - Sintomas: Ação perdida / rollback, Rubber banding / Fatores: Latência - Quem: Só eu, Só um recurso específico / Quando: Ao fazer ações específicas - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: mostrar com o resultado do servidor só o que precisa de confirmação, como números de dano, morte e recompensas, checar antes os motivos comuns de rejeição e, em caso de rejeição, devolver cooldown e recursos e mostrar o motivo. Servidor: deixar folga do tamanho do ping na checagem de alcance e posição do alvo, mandar o motivo na resposta de rejeição, coletar a taxa de rejeição por skill como métrica. - Números de referência: A resposta de rejeição chega ping + espera do tick depois de você apertar. Com ping de 150 ms, você passa cerca de 0,2 s achando que acertou. - No gráfico: Alto só em alguns (Taxa de rejeição do servidor por skill (por faixa de ping)) - Onde olhar: Coletar no servidor a taxa de rejeição por skill e os motivos (alcance, posição do alvo, cooldown, recursos), separados por faixa de RTT do jogador. No cliente, registrar quantas ações com feedback no cliente foram rejeitadas - Confirma se: As rejeições se concentram em certas skills e nos motivos de alcance e posição do alvo, e a taxa de rejeição sobe com o ping - Descarta se: Motivo de rejeição é cooldown ou recursos, sem relação com o ping: verificar se os valores de dados (cooldown, custo) diferem entre cliente e servidor. Sem rejeições, mas a animação só começa depois da resposta do servidor: aponta para “Feedback só depois da resposta do servidor (requisição-resposta)” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: O feedback no cliente é a melhor forma de esconder o ping. Só que, quanto mais diferem as informações que cliente e servidor usam para decidir (posição do adversário, recursos restantes), mais frequentes ficam as rejeições. Coletar a taxa de rejeição por skill como métrica facilita achar onde as decisões divergem. - Fontes: - [Using Gameplay Abilities in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-gameplay-abilities-in-unreal-engine) · Epic Games · Habilidades Local Predicted executam na hora no cliente, mas o servidor dá a decisão final e pode reverter o resultado - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Prevê no cliente o disparo da arma e reproduz o efeito antes, corrigindo o erro de predição com o resultado do servidor #### sy-path-mismatch · Divergência no cálculo de caminho na sincronização de comandos · Command sync with divergent pathing Se cliente e servidor trocam só “vá para cá” e cada lado calcula o caminho por conta própria, basta uma pequena diferença no cálculo para um personagem ou monstro seguir outro caminho e depois ser puxado de volta para o lugar certo. - Por quê → Efeito → Na tela: No movimento por clique e na perseguição de monstros, só o destino é enviado, e o cliente calcula o caminho por conta própria → Diferenças nos dados do terreno, colisões com outros personagens e ordem de cálculo diferente fazem o movimento seguir um caminho diferente do servidor → O monstro atravessa a parede e de repente é movido para outro lugar, o personagem que você clicou muda de direção como se deslizasse - Sintomas: Teleporte, Rubber banding / Fatores: Latência - Quem: Local ou canal específico, Só eu / Quando: Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: enviar também os pontos intermediários do caminho (waypoints), sincronizar a posição periodicamente. Cliente: corrigir as divergências de forma suave, usar os mesmos dados de terreno do servidor. - No gráfico: Picos aleatórios (Número e distância das correções de posição por entidade) - Onde olhar: Registrar por entidade a diferença entre a posição enviada pelo servidor e a calculada pelo cliente e marcar no mapa as coordenadas onde houve correção. Resumir o caminho ou a posição dos dois lados em checksums e comparar periodicamente ajuda a achar o momento em que começaram a divergir - Confirma se: As correções se concentram em certos terrenos (degraus, passagens estreitas, rampas) ou em lugares lotados e se repetem no mesmo ponto até para jogadores com métricas de rede normais - Descarta se: Correções em qualquer lugar, só nos momentos de pico de perda ou jitter: problema de conexão. Um monstro que pula na tela de várias pessoas ao mesmo tempo: verificar se a autoridade do monstro está em um cliente com lag - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Esse modelo é um dos motivos de jogos de movimento por clique e de tab target serem pouco sensíveis ao ping. Em troca, não há garantia de que os dois lados chegam ao mesmo resultado, por isso um mecanismo que sincroniza a posição de vez em quando é indispensável. Cálculos de ponto flutuante podem dar resultados ligeiramente diferentes conforme o tipo de CPU, o compilador e as opções de otimização (incluindo a diferença entre builds debug e release). Em arquiteturas como lockstep e rollback, que trocam só os inputs e supõem que os dois lados chegam ao mesmo resultado, essas pequenas diferenças podem se acumular até o estado do jogo das duas telas se separar (desync). - Fontes: - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · Mesmo sendo determinístico na mesma máquina, o resultado de ponto flutuante pode mudar com compilador, SO ou CPU diferentes - [State Synchronization](https://gafferongames.com/post/state_synchronization/) · Gaffer On Games · Enviando o estado junto com os inputs, dá para manter os dois lados sincronizados sem determinismo perfeito - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Perda de pacotes ou dois personagens tentando ir para o mesmo lugar fazem as simulações do servidor e do cliente divergirem, exigindo correção - [1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond](https://www.gamedeveloper.com/programming/1500-archers-on-a-28-8-network-programming-in-age-of-empires-and-beyond) · Game Developer · Diferenças minúsculas crescem com o tempo, e o caminho dos trabalhadores vai se desviando aos poucos. Comparação de mundo, entidades e pathfinding por checksum para achar a dessincronização (out-of-sync) - [Floating Point Determinism](https://gafferongames.com/post/floating_point_determinism/) · Gaffer On Games · O mesmo código de ponto flutuante pode dar resultados diferentes conforme o compilador, a arquitetura da CPU e o build debug ou release. Caso em que CPUs AMD e Intel deram valores um pouco diferentes em funções transcendentais - [/fp (Specify floating-point behavior)](https://learn.microsoft.com/en-us/cpp/build/reference/fp-specify-floating-point-behavior) · Microsoft · /fp:fast pode reordenar ou combinar operações de ponto flutuante e dar resultados diferentes das outras opções /fp, e operações combinadas em FMA também podem diferir de multiplicar e somar separadamente #### sy-low-send-rate · Taxa de envio de snapshots baixa · Low snapshot / update rate Se o servidor manda as atualizações de posição (snapshots) só algumas vezes por segundo, o buffer de interpolação precisa ser mais longo na mesma medida, e você vê os outros personagens mais no passado. - Por quê → Efeito → Na tela: Para economizar banda, as atualizações de posição saem só 5–10 vezes por segundo → Para desenhar com suavidade, o buffer precisa ter 2 vezes o intervalo entre pacotes (200–400 ms); se for curto, basta perder um pacote para os personagens pararem → As mudanças de direção do adversário aparecem tarde e divergem das decisões do servidor. Com buffer curto, engasgos, e teleporte quando há perda de pacotes - Sintomas: Engasgos, Teleporte, Ação perdida / rollback / Fatores: Latência, Perda de pacotes - Quem: Servidor inteiro / Quando: Sempre - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: enviar com frequência para alvos próximos ou em combate e raramente para os distantes, enviar só o que mudou (compressão delta) para reduzir o tamanho de cada envio e aumentar a frequência. Cliente: ajustar automaticamente o tamanho do buffer de interpolação ao intervalo entre pacotes. - Números de referência: Com 10 por segundo, o intervalo entre pacotes é de 100 ms e o buffer, de 200 ms. Somando os 75 ms de um sentido de um ping de 150 ms, você vê o adversário cerca de 0,3 s no passado. - No gráfico: Sempre alto desde o início (Intervalo de chegada dos pacotes por cliente, tamanho do buffer de interpolação) - Onde olhar: Em uma captura de pacotes no servidor, filtrar só o fluxo para um jogador e ver pacotes por segundo e intervalos no I/O Graphs do Wireshark. Com logs do jogo, ver junto o intervalo de atualização por entidade e a folga do buffer de interpolação do cliente (tempo restante até o próximo snapshot) - Confirma se: As atualizações de posição são sempre escassas, 5–10 por segundo (intervalo de 100–200 ms), e o buffer de interpolação passa de 200 ms ou a folga do buffer chega a 0 com frequência - Descarta se: Atualizações saem com frequência, mas só o intervalo de chegada oscila: aponta para jitter ou perda de pacotes. Só entidades distantes chegam raramente em lugares lotados: aponta para “Orçamento de envio e prioridade por conexão” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Com 10 atualizações por segundo, uma interpolação de 200 ms aguenta uma perda. O padrão do Half-Life é 20 por segundo com interpolação de 100 ms - [Snapshot Interpolation](https://gafferongames.com/post/snapshot_interpolation/) · Gaffer On Games · Com 10 por segundo, aguentar até duas perdas seguidas exige 350 ms de atraso; com 30 por segundo, cai para 150 ms - [State Synchronization](https://gafferongames.com/post/state_synchronization/) · Gaffer On Games · Acumulação de prioridade para enviar com mais frequência as entidades importantes, e envio do resto em rodízio dentro do limite de banda - [8.8. The “I/O Graphs” Window](https://www.wireshark.org/docs/wsug_html_chunked/ChStatIOGraphs.html) · Wireshark · Desenha em gráfico, por intervalo de tempo, o número de pacotes e bytes que batem com o filtro de exibição ### Problemas que só afetam alguns (24 causas) #### pt-slow-burst · Jogador com lag em avanço rápido na tela dos outros · Laggy player seen by others (bursty inputs) Para quem tem conexão ruim, os inputs chegam ao servidor irregulares e agrupados. Se o servidor aplica a cada tick o que recebeu, na tela dos outros esse personagem engasga e depois anda vários passos de uma vez. - Por quê → Efeito → Na tela: Os comandos de movimento do jogador com lag chegam 0 em um tick e 2–3 em outro → O servidor aplica tudo de uma vez no tick em que recebeu, e a posição do personagem muda em degraus → Na tela dos outros, só esse personagem engasga e depois avança vários passos de uma vez. O resto está normal - Sintomas: Avanço rápido, Teleporte / Fatores: Jitter, Perda de pacotes - Quem: Só um personagem parece estranho, Região ou operadora específica / Quando: Sempre, Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de desenvolvimento): Distribuir os comandos por igual com um buffer de input por jogador, aplicar no intervalo original usando os números de sequência dos inputs; só aumentar o buffer de interpolação na tela dos outros não basta (o próprio histórico de posição no servidor está em degraus). - O que fazer (Externo): Orientar o jogador com lag a usar conexão cabeada e verificar o Wi-Fi e o roteador. - Números de referência: Com jitter de 80 ms, em um servidor de 20 ticks (50 ms) o número de comandos por tick oscila entre 0 e 3. - No gráfico: Alto só em alguns (Comandos aplicados por tick por jogador, jitter por jogador) - Onde olhar: Em uma captura de pacotes no servidor, filtrar só os pacotes enviados pelo jogador reportado, contar quantos chegam a cada intervalo de tick (ex.: 50 ms) e comparar com outros jogadores. Com logs no servidor, ver por jogador o número de comandos de movimento aplicados a cada tick e os números de sequência dos inputs - Confirma se: Só os pacotes do jogador reportado chegam agrupados, alternando entre 0 e 2–3 por tick, com jitter e perda altos para ele, enquanto os pacotes dos outros chegam regulares. Diminui quando ele passa para conexão cabeada - Descarta se: Vários personagens em avanço rápido ao mesmo tempo: atraso no tick do servidor ou conexão de quem está vendo. Chegada e aplicação regulares, mas só esse personagem parece pular: problema de interpolação ou exibição do lado de quem vê - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Na arquitetura com autoridade do servidor, isso é o comportamento normal. O lag de um jogador lento só aparece para os outros como “esse jogador se movendo de um jeito estranho” e não afeta os comandos dos outros nem o movimento dos monstros. Mas o que envolve diretamente essa pessoa (trocas, mecânicas de party, registro de acerto no PvP) também atrasa. - Fontes: - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · O servidor coloca os inputs recebidos na fila de movimento de cada jogador, em ordem de tick, e preenche com predição quando ela esvazia. A correção só é visível para esse jogador, e os outros veem tudo suave - [State Synchronization](https://gafferongames.com/post/state_synchronization/) · Gaffer On Games · Até pacotes enviados 60 vezes por segundo chegam agrupados, 2 em um frame e 0 no seguinte - [Source SDK 2013: player.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player.cpp) · Valve · Distribui os comandos que chegaram juntos entre os ticks do servidor (meter out) #### pt-event-server · Avanço rápido em servidor que processa tudo ao chegar · Event-driven processing of bursty inputs Em um servidor que processa e avisa assim que cada pacote chega, as ações agrupadas de um jogador com lag são executadas imediatamente, uma atrás da outra. - Por quê → Efeito → Na tela: Requisições de skill e movimento do jogador com lag chegam agrupadas → O servidor executa em ordem assim que recebe e avisa todos na hora → Na tela dos outros, essa pessoa usa várias skills no mesmo instante ou se move como em avanço rápido - Sintomas: Avanço rápido / Fatores: Jitter - Quem: Só um personagem parece estranho / Quando: Ao fazer ações específicas, Sempre - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: executar respeitando o intervalo entre os horários de input das ações (aceitando o horário só dentro de uma margem), ou executar em sequência as ações agrupadas, sem rejeitá-las, espaçadas pelo intervalo mínimo (cooldown global); não checar o cooldown só pelo horário de chegada (inputs normais acabam ignorados). Cliente: enviar as ações com o horário do input. - No gráfico: Alto só em alguns (Intervalo de execução das ações por jogador) - Onde olhar: Registrar no log do servidor, por jogador, o horário de chegada e de execução de cada ação e o horário de input colocado pelo cliente (se houver), e comparar o intervalo de execução com o intervalo de input. Ver também o intervalo de chegada dos pacotes desse jogador em uma captura de pacotes no servidor - Confirma se: O intervalo de input é normal, mas os intervalos de chegada e execução no servidor estão espremidos em poucos ms, e esses momentos coincidem com o horário dos reports de avanço rápido dos outros jogadores - Descarta se: Intervalo de input já espremido: aponta para o cliente ou para macro. Execução no servidor regular, mas agrupada só na tela dos outros: conexão de quem está vendo - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · O servidor calcula o movimento a cada ServerMove recebido e define o intervalo de tempo pela diferença de timestamp em relação ao movimento anterior. Se a diferença para o horário do servidor for grande demais, descarta o movimento - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · Aplicar os inputs conforme chegam deixa o intervalo irregular mesmo enviando a 60 Hz, e o resultado oscila #### pt-input-buffer · Tamanho do buffer de input por jogador · Per-player server input buffer (jitter buffer) Se o servidor acumula um pouco os inputs de cada jogador e consome um por tick, os outros veem tudo suave, mas a ação do próprio jogador é confirmada no servidor mais tarde, na mesma medida. - Por quê → Efeito → Na tela: O servidor acumula no buffer os inputs do jogador com lag e aplica um por tick → Com buffer pequeno, ele esvazia com frequência e o personagem fica parado ou o servidor o move supondo o último input; com buffer grande, o input do próprio jogador é confirmado tarde → Pequeno: engasgos na tela dos outros. Grande: o resultado das skills do próprio jogador sai tarde (input lag) - Sintomas: Engasgos, Input lag / Fatores: Jitter - Quem: Só um personagem parece estranho, Só eu / Quando: Sempre - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: ajustar automaticamente o tamanho do buffer à conexão de cada jogador, consumir dois de cada vez para recuperar o atraso quando acumula, mandar o cliente de quem esvazia o buffer com frequência adiantar o envio dos inputs. Cliente: adiantar um pouco o envio dos inputs conforme a instrução do servidor (ajuste de tempo do cliente). - Números de referência: Varia por jogo, mas em geral é de 1–3 ticks. O VALORANT, com servidor de 128 ticks, mantém o buffer do servidor ainda menor, com meio frame em média (cerca de 4 ms). É comum o modelo adaptativo, que só aumenta o buffer para quem tem jitter alto. - No gráfico: Alto só em alguns (Tamanho do buffer de input e vezes que esvaziou, por jogador) - Onde olhar: Registrar no servidor, por jogador e a cada tick, quantos inputs restam no buffer, quantas vezes o buffer esvaziou e foi preenchido supondo o último input e o tempo entre a chegada do input e a aplicação - Confirma se: Quem tem buffer pequeno esvazia muitas vezes e, nesses momentos, para por um instante na tela dos outros; quem tem buffer grande tem o tempo entre input e aplicação aumentado na medida do buffer - Descarta se: Buffer quase nunca vazio, mas engasgos na tela dos outros: problema de interpolação de quem vê. Buffer curto e input lag alto mesmo assim: o próprio RTT ou espera dupla de tick - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · O servidor ajusta a referência de tempo do cliente para manter a fila de inputs com a menor latência possível, mas grande o bastante para absorver chegadas irregulares. A meta de buffer no servidor é meio frame em média - [NetworkTimeSystem class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkTimeSystem.html) · Unity · LocalBufferSec: tempo que o servidor mantém as mensagens do cliente em buffer. Adiantar o relógio do cliente faz as mensagens chegarem mais cedo ao servidor - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Jogadores com conexão ruim podem aumentar o valor do buffer #### pt-isp-validation · Falsos positivos da validação concentrados em uma operadora · Anti-cheat / movement validation false positives on bad ISPs Quem usa conexão com jitter alto tem os inputs chegando agrupados e cai com frequência nas checagens de velocidade e cooldown do servidor. - Por quê → Efeito → Na tela: O jitter de uma operadora ou região aumenta à noite → O servidor considera inputs normais que chegaram juntos como excesso de velocidade ou violação de cooldown → Só os assinantes dessa operadora têm rubber banding, skills rejeitadas e, nos casos graves, desconexão porque o servidor os expulsa - Sintomas: Rubber banding, Ação perdida / rollback, Desconexão / Fatores: Jitter - Quem: Região ou operadora específica, Só eu / Quando: Horário de pico à noite, Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Checar com tolerância acumulada ao longo de alguns segundos, afrouxar o critério considerando a qualidade da conexão (ping, jitter), ter um estágio de aviso antes do encerramento forçado, usar um buffer de input por jogador para distribuir por igual, a cada tick, os inputs que chegaram juntos e reduzir os próprios falsos positivos. - O que fazer (Equipe de infraestrutura): Verificar por faixa de horário a distribuição de perda e jitter por operadora e compartilhar com a equipe de desenvolvimento, verificar a rota no trecho dessa operadora (mtr nos dois sentidos) e, se preciso, mudar a rota ou acionar a operadora. - No gráfico: Alto só em certos horários (Rejeições na validação e encerramentos forçados por operadora (ASN), jitter por operadora) - Onde olhar: Anexar a operadora (ASN) do IP de conexão e o horário aos logs de rejeição, correção e encerramento forçado do servidor e contar por operadora e faixa de horário. A equipe de infraestrutura roda, no mesmo horário, mtr nos dois sentidos em direção a essa operadora para ver jitter e perda - Confirma se: Rejeições e encerramentos forçados se concentram em uma operadora e aumentam à noite, o jitter dessa operadora sobe no mesmo horário, e o deslocamento somado em janelas de alguns segundos fica dentro da regra - Descarta se: Repete só em certas contas, seja qual for a operadora: possível cheat real. Aumenta em todas as operadoras juntas: causa no servidor, com o tick atrasado aplicando os comandos agrupados (estouro do tick) - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Source SDK 2013: player.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player.cpp) · Valve · Comentário de desenvolvimento: o orçamento de comandos acumulado a cada tick barra o excesso de velocidade, mas limites mais rígidos geram engasgos até para jogadores normais - [RFC 2697: A Single Rate Three Color Marker](https://www.rfc-editor.org/rfc/rfc2697) · IETF · Token bucket: decide pela taxa média e pelo tamanho de burst permitido - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · Com grande diferença entre os timestamps do cliente e do servidor, descarta o movimento ou trata com um procedimento de resolução da diferença de tempo; calcula pelo horário do servidor para impedir speed hack #### pt-raid-member · Um membro da party com lag e a mecânica do boss · One laggy member in a synchronized mechanic Em mecânicas de raid em que todos precisam reagir juntos em um momento definido, a reação atrasada de um jogador com lag vira falha da party inteira. - Por quê → Efeito → Na tela: Mecânicas coletivas como “todos se espalham ao mesmo tempo” ou “um jogador aperta o botão” → Quem tem lag vê o aviso tarde, e o input dele também chega tarde → Wipe por causa de uma só pessoa, e os outros membros da party sentem que foi “por causa de quem está com lag” - Sintomas: Ação perdida / rollback, Input lag / Fatores: Latência - Quem: Local ou canal específico, Só um personagem parece estranho / Quando: Quando junta muita gente, Ao fazer ações específicas - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: dar à janela de tempo da mecânica uma folga do tamanho do ping, enviar o aviso antes pelo horário do servidor, design em que a falha de um não leva a wipe. Cliente: reproduzir o aviso recebido no horário do servidor. - No gráfico: Alto só em alguns (RTT dos jogadores que causaram a falha da mecânica) - Onde olhar: Registrar no log de mecânicas do servidor quem causou a falha, o horário de chegada do input dessa pessoa, a janela de tempo e o RTT e a perda dela - Confirma se: Os inputs que causaram o wipe são quase todos da mesma pessoa, o RTT dela é claramente mais alto que a média da party e o input chega logo depois da janela de tempo - Descarta se: Falhas distribuídas por igual entre os membros: a própria janela é curta demais (“Janela de tempo curta consumida pelo ping”). Input do jogador com lag chegou dentro da janela e mesmo assim falhou: código de decisão do servidor - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Método que agenda eventos pelo horário do servidor para que todos os reproduzam no mesmo instante - [Factors influencing the latency of simple reaction time (Frontiers in Human Neuroscience, 2015)](https://doi.org/10.3389/fnhum.2015.00131) · Frontiers · Tempo de reação simples médio de cerca de 231 ms #### pt-mob-control · Autoridade do monstro em um cliente com lag · Monster movement delegated to a player client Alguns jogos, para reduzir a carga do servidor, entregam o cálculo do movimento dos monstros ao cliente de um jogador próximo. Se a conexão dessa pessoa é ruim, o monstro se move de um jeito estranho na tela de todos. - Por quê → Efeito → Na tela: O servidor entrega o cálculo do movimento do monstro ao cliente do jogador mais próximo (ou do primeiro que chegou) → Os resultados reportados por esse jogador chegam ao servidor atrasados ou agrupados → Só esse monstro engasga e teleporta na tela de todos ao redor. Na tela de quem tem a autoridade, está normal - Sintomas: Teleporte, Engasgos, Avanço rápido / Fatores: Jitter, Perda de pacotes - Quem: Só um personagem parece estranho, Local ou canal específico / Quando: Sempre, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Passar a autoridade para quem tem conexão boa (por ping e perda), devolver a autoridade ao servidor na hora quando os reports pararem, calcular no próprio servidor os monstros importantes, como bosses. - No gráfico: Alto só em alguns (Intervalo dos reports de posição por monstro (por cliente com autoridade)) - Onde olhar: Registrar no servidor, para cada monstro, o cliente com autoridade e o intervalo de reports, o RTT e a perda desse cliente. Também dá para ver o intervalo de chegada dos pacotes enviados por esse cliente em uma captura de pacotes no servidor - Confirma se: Todos os monstros com movimento estranho estão sob a autoridade da mesma pessoa, o intervalo de reports dela é irregular ou some, e passar a autoridade para outro jogador resolve na hora - Descarta se: Monstros calculados pelo próprio servidor também pulam: atraso no tick do servidor ou conexão de quem está vendo. Continua pulando depois de trocar a autoridade: “Divergência no cálculo de caminho na sincronização de comandos” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Como quem tem a autoridade acha que está tudo normal, os reports chegam só como “o monstro está estranho”. Se todos, menos uma pessoa, veem o mesmo monstro estranho, verifique primeiro quem tem a autoridade sobre ele. - Fontes: - [Authority (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/terms-concepts/authority.html) · Unity · No modelo de autoridade distribuída, cada instância do jogo (cliente) tem autoridade sobre parte das entidades de rede e as calcula - [Distributed authority topologies (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/terms-concepts/distributed-authority.html) · Unity · Com a autoridade dividida entre clientes, não existe simulação única, e o jogo fica vulnerável a trapaça #### pt-heavy-char · Personagem com dados grandes demais · One character with oversized data (inventory, mail, buffs) Um personagem com milhares de itens ou mensagens no correio acumulados, ou com listas de amigos e bloqueados ou buffs fora do comum, tem várias vezes mais dados para carregar no login, salvar e enviar aos jogadores próximos. Fica lento só com esse personagem, seja qual for a conexão. - Por quê → Efeito → Na tela: Personagens antigos ou recompensas de evento acumulam milhares de entradas no inventário e no correio → Em cada login, troca de mapa e salvamento, o BD lê e grava tudo isso, e as informações de equipamento e buffs enviadas aos jogadores próximos também são grandes → Só esse personagem tem carregamento longo ao entrar e engasga ao abrir inventário ou correio. Em servidores que esperam o salvamento na thread do jogo, até quem está perto tem uma pausa curta - Sintomas: Não conecta / loading infinito, Input lag, Travamento / Fatores: Paralisação - Quem: Só eu, Só um recurso específico / Quando: Logo após login ou manutenção, Ao fazer ações específicas, Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de banco de dados (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Limite de armazenamento de inventário e correio e limpeza automática de mensagens antigas, carregar em partes só o necessário, salvar só o que mudou, fora da thread do jogo. - O que fazer (Equipe de infraestrutura): Procurar no log de queries lentas consultas lentas repetidas com o mesmo personagem e passar para a equipe de desenvolvimento, fornecer o ranking de personagens com mais linhas de itens e correio. - Números de referência: Se cada item é uma linha no BD, um personagem com 5.000 itens lê 5.000 linhas a cada login. São dezenas de vezes mais que um personagem comum. - No gráfico: Alto só em alguns (Tempo de login e salvamento por personagem, linhas lidas no BD por personagem) - Onde olhar: Procurar no log de queries lentas do BD (MySQL slow query log, PostgreSQL log_min_duration_statement) leituras e gravações lentas repetidas com o mesmo ID de personagem e tirar o ranking de linhas por personagem nas tabelas de itens e correio - Confirma se: As queries lentas se concentram em alguns IDs de personagem, esses personagens têm dezenas de vezes mais linhas de itens e correio que a média e ficam igualmente lentos em outro PC ou conexão - Descarta se: Outros personagens da mesma conta ou outros jogadores também lentos: aponta para hardware ou locks do BD. Personagem normal em outro PC: ambiente do jogador - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Se o mesmo personagem fica igualmente lento conectando de outro PC ou conexão, e os outros personagens da mesma conta estão normais, suspeite dos dados do personagem. É por isso que o nome do personagem é indispensável no report. - Fontes: - [Extraneous Fetching antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/extraneous-fetching/) · Microsoft Azure · Buscar mais dados do que o necessário aumenta a carga de I/O e deixa as respostas lentas - [PostgreSQL Documentation: Error Reporting and Logging](https://www.postgresql.org/docs/current/runtime-config-logging.html) · PostgreSQL · log_min_duration_statement: registra o SQL que passa de um certo tempo, para rastrear queries lentas - [The Slow Query Log](https://dev.mysql.com/doc/refman/8.4/en/slow-query-log.html) · MySQL · Log de queries lentas que registra as queries acima de long_query_time #### pt-phase · Diferença de canal, instância ou phasing · Different channel / instance / phase Se dois personagens estão em canais ou instâncias diferentes, ou em “fases” (phasing) diferentes, em que os NPCs visíveis dependem do progresso das quests, eles veem mundos diferentes. - Por quê → Efeito → Na tela: O segundo personagem foi alocado em outro canal ou está em outra etapa da quest → O servidor não envia esse NPC para esse personagem (comportamento normal) → O NPC falta só de um lado. Parece bug, mas funciona como projetado - Sintomas: Invisível / entidade fantasma / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC, Só eu / Quando: Sempre, Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: enviar ao cliente as informações de canal e fase, incluir no checklist de QA “verificar canal e etapa da quest dos dois personagens”. Cliente: mostrar canal e fase na tela. - No gráfico: Alto só em alguns (Número de entidades ao redor por cliente, canal e fase) - Onde olhar: Comparar na tela do jogo o número do canal e a etapa da quest dos dois personagens e olhar de novo depois de igualar canal e etapa. Com log de envio de entidades no servidor, verificar o motivo de o NPC não ter sido enviado a esse personagem (canal, fase) - Confirma se: Os dois personagens estão em canais ou etapas de quest diferentes, e o NPC aparece quando ficam iguais - Descarta se: Mesmo canal e mesma etapa, mas falta só de um lado: aponta para “Mensagens de spawn descartadas durante o carregamento”, “Perda do burst de spawns logo após a entrada” ou “Condição de corrida no registro da área de interesse (AOI)” - Como verificar: Verificação no ambiente do jogador - Saiba mais: Verifique também se o progresso das quests é salvo por conta ou por personagem. Se forem dois personagens da mesma conta, o progresso de um pode mudar a fase do outro. - Fontes: - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · O servidor só replica os atores relevantes para cada conexão e não envia os que não são - [Object visibility (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/basics/object-visibility.html) · Unity · CheckObjectVisibility define as entidades visíveis para cada cliente, e as entidades ocultas não são enviadas a esse cliente #### pt-loading-drop · Mensagens de spawn descartadas durante o carregamento · Spawn messages dropped before the client is ready Assim que o personagem entra na zona, o servidor envia as mensagens de spawn dos NPCs próximos, mas o cliente ainda está carregando o mapa e descarta essas mensagens. - Por quê → Efeito → Na tela: O servidor envia as mensagens de spawn das entidades próximas logo após processar a entrada → O cliente está carregando, ainda não tem o handler de mensagens e descarta as mensagens → O servidor considera que já enviou e não envia de novo. O NPC fica invisível até sair do campo de visão e voltar - Sintomas: Invisível / entidade fantasma / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC, Só eu / Quando: Logo após login ou manutenção, Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: enviar “pronto” ao terminar o carregamento, ou guardar os pacotes recebidos durante o carregamento e processá-los depois. Servidor: enviar as informações do entorno só depois de receber o “pronto”. - Números de referência: Se dois clientes no mesmo PC carregam ao mesmo tempo, ou se o que está carregando é uma janela em segundo plano, eles dividem CPU e disco e o processamento é limitado, então o carregamento desse lado pode ficar várias vezes mais longo. O mesmo bug também aparece quando o servidor passa a processar a entrada mais rápido. - No gráfico: Alto só em alguns (Tempo de carregamento por cliente, mensagens descartadas durante o carregamento) - Onde olhar: Comparar o número e o tipo de mensagens que o cliente recebeu e descartou durante o carregamento, e o horário em que o carregamento terminou, com o horário em que o servidor enviou as mensagens de spawn. Fica fácil reproduzir carregando dois clientes ao mesmo tempo no mesmo PC ou deixando o que carrega como janela em segundo plano - Confirma se: O servidor enviou a mensagem de spawn do NPC invisível, ela chegou antes do fim do carregamento, e o número de mensagens descartadas subiu nesse intervalo. Só acontece no cliente que demora mais para carregar - Descarta se: Mensagem de spawn chegou depois do fim do carregamento e mesmo assim o NPC está invisível: aponta para “Perda do snapshot de referência (baseline)” ou “Confusão por reutilização de ID de entidade”. Servidor nem enviou a mensagem desse NPC: aponta para “Condição de corrida no registro da área de interesse (AOI)” ou “Diferença de canal, instância ou phasing” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [NetworkConfig class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkConfig.html) · Unity · SpawnTimeout: mensagens de entidades ainda não criadas ficam retidas e são descartadas se a entidade não for criada dentro do prazo - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · Atores que deixam de ser relevantes são apagados no cliente e, quando voltam a ser relevantes, são replicados de novo #### pt-aoi-race · Condição de corrida no registro da área de interesse (AOI) · Interest-management race on enter/leave Se o momento em que o personagem é registrado na grade da área de interesse coincide com o momento em que um NPC muda de célula, a mensagem de spawn desse NPC pode se perder. - Por quê → Efeito → Na tela: O processamento de entrada, troca de canal ou teletransporte coincide com o movimento de um NPC no mesmo instante → O NPC fica de fora do cálculo de “entidades que passaram a ser visíveis” → Só alguns NPCs específicos ficam invisíveis, ou um NPC que já foi embora continua lá - Sintomas: Invisível / entidade fantasma / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC, Só eu / Quando: Em movimento ou ao trocar de mapa, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Processar a atualização de visibilidade em uma só thread e em uma ordem fixa, ressincronizar periodicamente a “lista de visíveis” inteira. - No gráfico: Picos aleatórios (Diferenças entre a lista de visíveis do servidor e a lista de entidades do cliente) - Onde olhar: Registrar no servidor, com o número do tick, o registro na grade da área de interesse, a mudança de célula das entidades e o envio de mensagens de spawn e despawn, e comparar periodicamente a “lista de visíveis” do servidor com a lista que o cliente tem - Confirma se: O NPC que faltou mudou de célula no mesmo tick do processamento de entrada ou teletransporte do personagem, e não há registro de envio de mensagem de spawn para esse NPC - Descarta se: Mensagem de spawn enviada, mas o cliente não recebeu ou descartou: aponta para a entrega (“Perda do burst de spawns logo após a entrada”, “Mensagens de spawn descartadas durante o carregamento”). Sempre o mesmo NPC faltando: aponta para fase ou opções de exibição diferentes - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Replication Graph in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/replication-graph-in-unreal-engine) · Epic Games · MMORPGs e jogos parecidos dividem o mundo em uma grade, mantêm uma lista de atores por célula e enviam com base na célula onde o cliente está - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · A relevância é decidida para cada conexão, e atores que deixam de ser relevantes são apagados no cliente #### pt-baseline · Perda do snapshot de referência (baseline) · Lost baseline for delta compression No modelo em que o servidor só manda “o que mudou desde a última vez”, se a informação completa enviada uma vez no início (a referência) se perde, as mudanças seguintes não podem ser aplicadas. - Por quê → Efeito → Na tela: O pacote com a informação completa da entidade (referência) se perde ou é descartado antes de ser processado → O cliente não tem onde aplicar as mudanças seguintes e as ignora → A entidade fica invisível ou aparece de repente muito tempo depois - Sintomas: Invisível / entidade fantasma, Teleporte / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC, Só eu / Quando: Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: retransmitir a referência sempre, até receber a confirmação (ACK), e montar as mudanças só a partir de referências que o cliente confirmou ter recebido. Cliente: enviar a confirmação (ACK) da referência só depois de aplicá-la de fato, pedir de novo ao servidor quando receber mudanças de uma entidade desconhecida. - No gráfico: Picos aleatórios (Mudanças recebidas de entidades desconhecidas) - Onde olhar: Cruzar quantas vezes o cliente descartou mudanças recebidas sem referência, e de quais IDs de entidade, com o horário em que o servidor enviou a referência dessa entidade e o horário em que recebeu o ACK. Reproduzir em ambiente de desenvolvimento inserindo perda (loss do tc netem, taxa de perda de pacotes da emulação de rede do Unreal) - Confirma se: Para a entidade invisível, o servidor enviou a referência, não recebeu o ACK e mesmo assim continuou mandando só as mudanças, e o cliente descartou essas mudanças - Descarta se: Referência confirmada com ACK e aplicada no cliente, mas a entidade continua invisível: aponta para “Mensagem de despawn perdida (entidade fantasma)” ou “Confusão por reutilização de ID de entidade” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Snapshot Compression](https://gafferongames.com/post/snapshot_compression/) · Gaffer On Games · As mudanças só devem ser montadas a partir de uma referência (baseline) que o outro lado confirmou (ack) ter recebido, e o estado inicial é enviado separadamente - [Quake III Arena source: code/server/sv_snapshot.c](https://raw.githubusercontent.com/id-Software/Quake-III-Arena/master/code/server/sv_snapshot.c) · id Software · Faz compressão delta a partir do snapshot que o cliente confirmou e, se a referência for antiga demais, envia o snapshot completo - [tc-netem(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-netem.8.html) · iproute2 · Ferramenta de teste que insere atraso e jitter (delay TIME JITTER) e perda (loss random PERCENT) nos pacotes de saída para imitar uma rede real - [Using Network Emulation in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-network-emulation-in-unreal-engine) · Epic Games · Testa com latência mínima e máxima e taxa de perda de pacotes configuradas no servidor e no cliente; no console, a configuração usa comandos como NetEmulation.PktLag #### pt-ghost · Mensagem de despawn perdida (entidade fantasma) · Missed despawn (ghost entity) No caso inverso, se a mensagem de que algo “sumiu” se perde, NPCs ou jogadores que já morreram ou saíram continuam só na sua tela. - Por quê → Efeito → Na tela: Mensagens de morte, de saída ou de saída do campo de visão se perdem ou chegam fora de ordem → O cliente acha que a entidade ainda está lá → Monstro que não reage aos golpes, jogador que já saiu continua parado lá - Sintomas: Invisível / entidade fantasma / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC, Só eu / Quando: Aleatoriamente, de vez em quando, Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: enviar periodicamente a “lista do que está visível agora”. Cliente: apagar as entidades que não estão na lista, esconder entidades que deveriam se mover e passam muito tempo sem atualização. - No gráfico: Picos aleatórios (Entidades que só existem no cliente) - Onde olhar: Comparar a “lista do que está visível agora” enviada pelo servidor com a lista de entidades do cliente, contar as que só existem no cliente e cruzar pelo ID de entidade os logs de envio e recebimento das mensagens de despawn - Confirma se: O servidor enviou a mensagem de despawn da entidade fantasma, mas não há registro de recebimento no cliente, ou o despawn chegou antes do spawn e a ordem se inverteu - Descarta se: A entidade também continua na lista de visíveis do servidor: falha na limpeza de entidades no servidor. Logo depois de surgir uma nova entidade com o mesmo ID: aponta para “Confusão por reutilização de ID de entidade” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · Atores dinâmicos que deixam de ser relevantes são apagados no cliente - [Object visibility (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/basics/object-visibility.html) · Unity · Ao esconder uma entidade, o cliente faz despawn e a apaga #### pt-spawn-burst · Perda do burst de spawns logo após a entrada · Initial spawn burst lost (unreliable channel, receive buffer, fragmentation) No instante em que o personagem entra na zona, o servidor envia de uma vez as informações de spawn de dezenas a centenas de entidades próximas. Se isso vai por um canal não confiável (unreliable), ou se o buffer de recepção estoura enquanto o socket não é lido durante o carregamento, parte se perde e não é reenviada. - Por quê → Efeito → Na tela: Logo após a entrada, as informações de spawn chegam todas em um intervalo curto → O cliente que está carregando lê o socket tarde e o buffer de recepção do SO estoura, ou um pacote UDP grande é fragmentado e some inteiro se um único fragmento se perde. Em canal não confiável, nada é reenviado → Faltam alguns NPCs só no cliente que carrega mais devagar. Eles aparecem depois de sair do campo de visão e voltar - Sintomas: Invisível / entidade fantasma / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC, Só eu / Quando: Logo após login ou manutenção, Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: enviar mensagens de spawn e despawn sempre por canal confiável, com retransmissão garantida, e dividir a informação inicial em partes. Cliente: receber em uma thread separada do carregamento, aumentar o buffer de recepção. - Números de referência: O padrão do buffer de recepção UDP no PC varia por SO, mas costuma ser de dezenas a centenas de KB. Se as informações de entrada de uma cidade lotada passam disso, basta o socket ficar um instante sem ser lido por causa do carregamento para estourar. - No gráfico: Pico logo após abrir ou manutenção (Volume recebido logo após a entrada, mensagens de spawn perdidas) - Onde olhar: Comparar o número de mensagens de spawn que o servidor enviou logo após a entrada com o número que o cliente recebeu e ver por qual canal (confiável ou não confiável) foram. Em uma captura de pacotes no servidor, ver o volume enviado a esse jogador logo após a entrada e os pacotes fragmentados (filtro do Wireshark ip.flags.mf == 1 || ip.frag_offset > 0) - Confirma se: Foram recebidas menos mensagens do que enviadas, as que faltam estão concentradas no pico logo após a entrada, e o envio foi por canal não confiável ou os pacotes grandes foram fragmentados. Acontece mais no cliente que carrega mais devagar - Descarta se: Número enviado igual ao recebido, mas entidade invisível: foi descartada depois de recebida (“Mensagens de spawn descartadas durante o carregamento”) ou há problema no cálculo de visibilidade. Falta a qualquer momento, sem relação com a entrada: perda de pacotes na conexão - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · Um pacote fragmentado some inteiro se um único fragmento se perde - [UDP vs. TCP](https://gafferongames.com/post/udp_vs_tcp/) · Gaffer On Games · O UDP não garante entrega nem ordem, então a própria aplicação precisa detectar os pacotes perdidos e reenviá-los - [Socket.ReceiveBufferSize Property](https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.receivebuffersize) · Microsoft · O tamanho padrão do buffer de recepção do socket varia por SO - [Display Filter Reference: Internet Protocol Version 4](https://www.wireshark.org/docs/dfref/i/ip.html) · Wireshark · Filtra pacotes IP fragmentados com ip.flags.mf (More fragments) e ip.frag_offset (Fragment Offset) #### pt-id-reuse · Confusão por reutilização de ID de entidade · Entity ID reused without a generation counter Se o servidor reutiliza o mesmo ID de entidade quando um NPC morto reaparece, o cliente que perdeu a mensagem de despawn nesse meio-tempo toma o NPC novo pelo antigo. - Por quê → Efeito → Na tela: O NPC morre e reaparece com o mesmo ID de entidade → O cliente que perdeu a mensagem de despawn ignora a mensagem de spawn, achando que é “uma entidade que já conhece”, ou mantém o estado de morto → O NPC falta ou aparece caído em uma só tela, às vezes com a aparência de outro NPC - Sintomas: Invisível / entidade fantasma / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC, Só eu / Quando: Aleatoriamente, de vez em quando, Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: incluir um número de geração no ID da entidade para distinguir a reutilização. Cliente: ao receber mensagem de spawn de um ID já conhecido, apagar a entidade antiga e criar uma nova. - No gráfico: Picos aleatórios (Mensagens de spawn de IDs já conhecidos) - Onde olhar: Registrar no servidor o horário de criação e remoção de cada ID de entidade (com o número de geração, se houver) e contar quantas vezes o cliente recebeu mensagem de spawn de um ID já conhecido e quantas remoções e recriações foram tratadas como “sem mudança” na atualização de visibilidade - Confirma se: O NPC invisível ou caído tem o mesmo ID de um NPC que acabou de morrer, e nesse intervalo o cliente não recebeu a mensagem de despawn ou o servidor não enviou nem a de despawn nem a de spawn - Descarta se: Se o ID tem número de geração e ele é usado na comparação, a causa é outra. Entidade invisível sem ID reutilizado: aponta para perda da mensagem de spawn - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Saiba mais: Também acontece no lado do servidor. Se a lista de entidades no campo de visão é comparada só pelo ID, um NPC que morreu e reapareceu com o mesmo ID entre duas atualizações de visibilidade é visto como “sem mudança”, e nenhuma das duas mensagens (despawn e spawn) é enviada. Se o momento da atualização de visibilidade é diferente para cada jogador, só os clientes pegos nesse instante têm o problema. - Fontes: - [Entity struct (Entities 1.3)](https://docs.unity3d.com/Packages/com.unity.entities@1.3/api/Unity.Entities.Entity.html) · Unity · Uma Entity é formada por um Index e um número de geração (Version), o que permite saber se um Index reutilizado ainda é válido - [NetworkConfig class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkConfig.html) · Unity · RecycleNetworkIds e NetworkIdRecycleDelay: reutilizam um ID de rede só depois de deixá-lo livre por um tempo #### pt-port-collision · Conflito de porta UDP fixa · Two clients bound to the same local UDP port Se o cliente foi feito para usar uma porta local fixa, o segundo cliente no mesmo PC não consegue usar a porta ou divide os pacotes com o primeiro. - Por quê → Efeito → Na tela: Os dois clientes tentam abrir a mesma porta UDP local (compartilhada à força com a opção de reutilização) → O SO entrega os pacotes que chegam a só um dos sockets, ou não garante qual deles recebe. O roteador e o servidor também veem os dois clientes como o mesmo endereço → Um dos lados não recebe os pacotes do mundo, e NPCs e outros jogadores ficam invisíveis ou a conexão cai - Sintomas: Invisível / entidade fantasma, Desconexão, Não conecta / loading infinito / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC / Quando: Logo após login ou manutenção, Sempre - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: deixar o SO escolher a porta local automaticamente (bind na porta 0). Servidor: distinguir as conexões pelo token de sessão emitido para cada uma. - No gráfico: Alto só em alguns (Pacotes recebidos por cliente) - Onde olhar: No PC do jogador, com os dois clientes abertos, ver no prompt de comando, com netstat -ano -p udp, a porta UDP local aberta por cada processo do jogo (PID). No servidor, verificar se as duas sessões chegam com o mesmo IP público e a mesma porta - Confirma se: Os dois processos do jogo estão vinculados à mesma porta local, ou as duas sessões aparecem no servidor com o mesmo IP e porta. Com um só cliente aberto, tudo normal - Descarta se: Os dois clientes usam portas locais diferentes e mesmo assim um deles tem problema: aponta para “Bug na separação de sessões por IP ou dispositivo” ou “Restrição a múltiplos clientes” - Como verificar: Verificação no ambiente do jogador - Fontes: - [Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE](https://learn.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse) · Microsoft · Um segundo bind na mesma porta com SO_REUSEADDR sequestra a porta, e não dá para saber qual socket vai receber os pacotes - [bind function (winsock.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-bind) · Microsoft · Fazer bind na porta 0 atribui uma porta única da faixa de portas dinâmicas (49152–65535) - [netstat](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/netstat) · Microsoft · -a mostra portas TCP e UDP, -n endereços numéricos, -o o ID do processo (PID), e -p udp mostra só UDP #### pt-session-key · Bug na separação de sessões por IP ou dispositivo · Session keyed by IP or machine ID Se o servidor ou um servidor intermediário distingue as conexões por IP ou ID do dispositivo, dois clientes no mesmo PC (mesmo IP público) são tratados como uma só pessoa. - Por quê → Efeito → Na tela: Tabela de sessões montada por IP ou por IP + ID do dispositivo → Os dados do segundo cliente sobrescrevem a primeira sessão ou se misturam com ela → Em um lado os NPCs ficam invisíveis, e no outro a conexão cai ou chegam dados de outra pessoa - Sintomas: Invisível / entidade fantasma, Desconexão / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC, Mesma casa, Região ou operadora específica / Quando: Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: distinguir as conexões por um token de sessão único por conexão, tanto no servidor quanto nos servidores intermediários; corrigir sem falta, porque várias pessoas na mesma casa (atrás do NAT do roteador) e usuários de rede móvel em que a operadora divide um IP entre vários assinantes (CGNAT) têm o mesmo problema. Cliente: usar um token de sessão recebido separadamente por cada cliente aberto. - No gráfico: Alto só em alguns (Sessões simultâneas no mesmo IP público, sessões sobrescritas) - Onde olhar: Registrar nos logs do servidor e dos servidores intermediários a chave usada para achar a sessão, o token de sessão e o IP e porta do cliente, e ver se a sessão existente mudou no momento em que chegou a segunda conexão do mesmo IP. Reproduz abrindo dois clientes, um depois do outro, no mesmo PC - Confirma se: No momento em que o segundo cliente se conecta, o endereço ou os dados de personagem da primeira sessão mudam, e outros jogadores atrás do mesmo roteador ou da mesma rede móvel (CGNAT) também têm as mesmas desconexões - Descarta se: Duas sessões do mesmo IP mantidas separadas, com tokens diferentes: a causa é outra. Os dois processos usam a mesma porta local: “Conflito de porta UDP fixa” - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [RFC 6269: Issues with IP Address Sharing](https://www.rfc-editor.org/rfc/rfc6269) · IETF · Quando vários assinantes compartilham um endereço IPv4 por NAT ou CGN, não dá para distinguir usuários só pelo IP #### pt-multiclient · Restrição a múltiplos clientes · Multi-client restriction policy Se o módulo de segurança ou uma política do servidor limita vários clientes em um PC, o segundo cliente é impedido de abrir ou de conectar, ou o primeiro que foi aberto é desconectado. Alguns jogos bloqueiam só as funções dos clientes adicionais. - Por quê → Efeito → Na tela: O módulo de segurança detecta execução duplicada, ou o servidor limita conexões adicionais do mesmo dispositivo → Recusa a segunda execução ou conexão, ou derruba um dos lados. Raramente, bloqueia só algumas funções do cliente adicional → Não conecta ou um dos lados cai. Em jogos que só bloqueiam funções, NPCs e lojas ficam invisíveis em um dos lados - Sintomas: Não conecta / loading infinito, Invisível / entidade fantasma, Desconexão / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC / Quando: Logo após login ou manutenção - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: se for limitar, mostrar uma mensagem clara, configurar exceção para QA no módulo de segurança. Servidor: configurar exceção para QA também no limite de conexões do mesmo dispositivo. - No gráfico: Alto só em alguns (Recusas e desconexões por motivo (conexão duplicada)) - Onde olhar: Ver a mensagem que aparece ao abrir o segundo cliente e a mensagem de desconexão do primeiro. Verificar se os logs de recusa de conexão e encerramento forçado do servidor registram códigos de motivo como conexão duplicada ou mesmo dispositivo - Confirma se: No momento da segunda execução ou conexão aparece uma mensagem de recusa ou o primeiro cliente cai por conexão duplicada, e com um só cliente aberto não há problema - Descarta se: Os dois conectam sem motivo de recusa ou desconexão, mas só um não vê os NPCs: aponta para “Conflito de porta UDP fixa”, “Bug na separação de sessões por IP ou dispositivo” ou causas de carregamento ou exibição - Como verificar: Verificação no ambiente do jogador - Fontes: - [CreateMutexW function (synchapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexw) · Microsoft · Se um mutex nomeado já existe, a função retorna ERROR_ALREADY_EXISTS, o que serve para detectar execução duplicada e limitar a uma instância #### pt-background · Limitação de processamento da janela em segundo plano · Background window throttling Em um cliente que está em janela em segundo plano, o jogo, a engine e o SO reduzem frames e processamento. Os pacotes recebidos não são processados a tempo e acumulam ou estouram o buffer. - Por quê → Efeito → Na tela: Limite de frames em segundo plano nas opções do jogo ou no driver de vídeo (ex.: o driver da NVIDIA permite escolher de 20 a 200 por segundo), economia de energia, configuração da engine que pausa em segundo plano. O SO também prioriza CPU e GPU para a janela em primeiro plano → Menos pacotes processados por frame, a fila acumula, e quando o buffer de recepção estoura os pacotes são descartados → Ao trazer a janela para a frente, tudo aparece de uma vez, ou alguns NPCs nunca aparecem - Sintomas: Invisível / entidade fantasma, Avanço rápido, Desconexão / Fatores: Paralisação, Perda de pacotes - Quem: Só um dos clientes no mesmo PC / Quando: Depois de ficar parado, Sempre - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de desenvolvimento): Manter a recepção de rede em uma thread separada do game loop, garantir uma vazão mínima de processamento mesmo em segundo plano, ligar a opção de execução em segundo plano da engine (no Unity, runInBackground). - O que fazer (Externo): Orientar os jogadores a desligar o limite de frames em segundo plano do driver de vídeo e o modo de economia de energia do PC. - Números de referência: No Unity, com a opção runInBackground desligada, o game loop para no instante em que a janela perde o foco. Se a recepção acontece só nesse loop, nenhum pacote é processado nesse tempo. - No gráfico: Lacuna e depois tudo junto (Intervalo entre frames do cliente, pacotes processados por frame) - Onde olhar: No mesmo PC, deixar uma janela na frente e outra atrás e comparar trocando os papéis. Medir o intervalo entre frames dos dois processos com o PresentMon e, com logs do jogo, ver o estado de foco da janela e os pacotes processados por frame - Confirma se: Só em segundo plano o intervalo entre frames aumenta muito (com limite do driver, achata no intervalo correspondente ao número de frames configurado) ou o processamento para, e ao trocar as janelas o problema passa para o outro cliente - Descarta se: Acontece igual na janela da frente: a causa não é o limite em segundo plano. Sempre o mesmo cliente com problema, seja qual for a posição da janela: opções de exibição ou versão diferentes - Como verificar: Verificação no ambiente do jogador - Fontes: - [Application.runInBackground](https://docs.unity3d.com/ScriptReference/Application-runInBackground.html) · Unity · O padrão de runInBackground é false, e nesse caso o app pausa em segundo plano - [Manage 3D Settings (reference) — NVIDIA Control Panel Help](https://www.nvidia.com/content/Control-Panel-Help/vLatest/en-us/mergedProjects/nv3d/Manage_3D_Settings_(reference).htm) · NVIDIA · Background Application Max Frame Rate: limita o FPS máximo de jogos em segundo plano a um valor entre 20 e 200 - [Priority Boosts](https://learn.microsoft.com/en-us/windows/win32/procthread/priority-boosts) · Microsoft · O Windows eleva a prioridade do processo da janela em primeiro plano acima da dos processos em segundo plano - [PresentMon README](https://raw.githubusercontent.com/GameTechDev/PresentMon/main/README.md) · Intel · Ferramenta que coleta, por app, o tempo de frame de CPU, GPU e tela de apps gráficos no Windows #### pt-asset-lock · Conflito de acesso simultâneo a arquivos de cache e assets · Shared cache / asset file lock conflicts Se dois clientes escrevem ao mesmo tempo na mesma pasta de cache ou bloqueiam arquivos, um deles não consegue carregar modelos e texturas de NPC. - Por quê → Efeito → Na tela: Os dois clientes escrevem ao mesmo tempo nos arquivos de cache e de patch da mesma pasta de instalação → Falha no lock do arquivo ou leitura de arquivo escrito pela metade faz o carregamento falhar → NPC que mostra o nome, mas não tem modelo, ou NPC transparente - Sintomas: Invisível / entidade fantasma / Fatores: Paralisação - Quem: Só um dos clientes no mesmo PC / Quando: Logo após login ou manutenção, Em movimento ou ao trocar de mapa - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Pasta de cache separada por cliente, nova tentativa quando o lock do arquivo falhar, mostrar pelo menos um modelo padrão quando o carregamento falhar. - No gráfico: Alto só em alguns (Falhas de carregamento de assets por cliente) - Onde olhar: No PC do jogador, filtrar no Process Monitor só os caminhos das pastas de instalação e cache do jogo e ver o resultado das aberturas e escritas de arquivo dos dois processos do jogo. Com log do cliente, procurar falhas de carregamento de assets e o código de erro de abertura de arquivo (ERROR_SHARING_VIOLATION) - Confirma se: A abertura do arquivo do modelo invisível terminou em violação de compartilhamento ou falha de lock, e no mesmo momento o outro cliente estava escrevendo nesse arquivo. Some com um só cliente aberto ou com pastas de instalação e cache separadas - Descarta se: Mesmo modelo invisível com um só cliente aberto: arquivo corrompido ou “Versão ou dados do cliente incompatíveis”. Arquivo aberto sem erro, mas o modelo não é desenhado: “Falha de streaming por falta de memória ou VRAM” - Como verificar: Verificação no ambiente do jogador - Fontes: - [Creating and Opening Files](https://learn.microsoft.com/en-us/windows/win32/fileio/creating-and-opening-files) · Microsoft · Um arquivo aberto sem modo de compartilhamento não pode ser aberto por outro processo, que recebe ERROR_SHARING_VIOLATION - [Process Monitor](https://learn.microsoft.com/en-us/sysinternals/downloads/procmon) · Microsoft · Registra em tempo real a atividade de sistema de arquivos, Registro do Windows e processos e permite filtrar por qualquer campo, como o caminho #### pt-vram · Falha de streaming por falta de memória ou VRAM · Memory / VRAM exhaustion Quando dois clientes dividem a memória de vídeo, não sobra espaço para carregar os modelos e texturas novos, e parte deles não é desenhada. - Por quê → Efeito → Na tela: Os dois clientes dividem VRAM e RAM. O SO também pode reduzir primeiro a cota de memória de vídeo da janela em segundo plano → A engine não consegue carregar os novos modelos e texturas ou fica descarregando e carregando de novo → NPCs aparecem tarde, borrados ou invisíveis, engasgos - Sintomas: Invisível / entidade fantasma, Engasgos / Fatores: Paralisação - Quem: Só um dos clientes no mesmo PC / Quando: Em movimento ou ao trocar de mapa, Quando junta muita gente - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Externo (Externo) - O que fazer (Equipe de desenvolvimento): Ajuste automático de qualidade pelo orçamento de memória, mostrar modelo substituto quando o carregamento falhar. - O que fazer (Externo): Orientar quem abre dois clientes juntos a baixar a qualidade gráfica ou usar o modo leve, informar a VRAM e a RAM recomendadas. - No gráfico: Achata ao bater no limite (Uso de memória dedicada da GPU por processo) - Onde olhar: No PC do jogador, adicionar a coluna de memória dedicada da GPU na guia Detalhes do Gerenciador de Tarefas e comparar a soma do uso dos dois clientes com a VRAM da placa de vídeo. No jogo, registrar o orçamento (Budget) e o uso atual (CurrentUsage) informados pelo QueryVideoMemoryInfo do DXGI - Confirma se: A soma do uso dos dois clientes achata perto da capacidade de VRAM, e as falhas de carregamento de modelos e texturas se concentram nos momentos em que o uso atual passa do orçamento. Some ao baixar a qualidade ou abrir um só cliente - Descarta se: Sobra VRAM e mesmo assim não aparece: aponta para “Conflito de acesso simultâneo a arquivos de cache e assets” ou “Opções de exibição diferentes” - Como verificar: Verificação no ambiente do jogador - Fontes: - [Residency (Direct3D 12)](https://learn.microsoft.com/en-us/windows/win32/direct3d12/residency) · Microsoft · O orçamento de memória de vídeo pode cair muito ao trocar para outro app, e passar do orçamento causa pausas ou falhas ao criar recursos. Fora do primeiro plano, nem a reserva é garantida - [GPUs in the task manager](https://devblogs.microsoft.com/directx/gpus-in-the-task-manager/) · Microsoft · Adicionando colunas na guia Detalhes do Gerenciador de Tarefas, dá para ver o uso de memória dedicada e compartilhada da GPU por processo. A memória dedicada da GPU é a VRAM da placa de vídeo - [DXGI_QUERY_VIDEO_MEMORY_INFO structure (dxgi1_4.h)](https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_4/ns-dxgi1_4-dxgi_query_video_memory_info) · Microsoft · Budget (orçamento de memória de vídeo definido pelo SO) e CurrentUsage (uso atual do app). Uso acima do orçamento pode causar engasgos #### pt-display-option · Opções de exibição diferentes · Different display settings Se opções como limite de personagens exibidos, ocultar nome acima do personagem ou modelo de NPC e modo leve estão diferentes nos dois clientes, cada um vê coisas diferentes. - Por quê → Efeito → Na tela: Só um dos clientes com “limite de personagens exibidos ao redor” ou modo leve → NPCs distantes ou de baixa prioridade não são desenhados (comportamento normal) → O NPC falta só de um lado - Sintomas: Invisível / entidade fantasma / Fatores: Paralisação - Quem: Só um dos clientes no mesmo PC, Só eu / Quando: Quando junta muita gente, Sempre - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Indicar que a entidade está oculta por uma opção, separar o arquivo de configuração por cliente para que não se misturem. - No gráfico: Alto só em alguns (Entidades desenhadas na tela por cliente) - Onde olhar: Comparar lado a lado, nos dois clientes, o limite de personagens exibidos, a ocultação de nome e modelo e o modo leve, e igualar um ao outro. Verificar também se os dois clientes usam o mesmo arquivo de configuração e sobrescrevem um ao outro - Confirma se: Com as configurações iguais, as duas telas ficam iguais, e o NPC que não aparecia era uma entidade distante fora do limite de exibição ou de baixa prioridade - Descarta se: Mesmo com as configurações iguais, falta só de um lado: aponta para “Diferença de canal, instância ou phasing” ou perda da mensagem de spawn - Como verificar: Verificação no ambiente do jogador - Fontes: - [Changing the Quantity of Characters Displayed On-screen (FINAL FANTASY XIV UI Guide)](https://na.finalfantasyxiv.com/uiguide/faq/faq-other/setting_ch_quantity.html) · Square Enix · A configuração de limite de exibição (Character and Object Quantity) ajusta quantos personagens e objetos são desenhados na tela #### pt-version · Versão ou dados do cliente incompatíveis · Client version / data table mismatch Se o segundo cliente é outra instalação ou não terminou o patch, ele não conhece os novos IDs de NPC enviados pelo servidor e os ignora em silêncio. - Por quê → Efeito → Na tela: Instalação em outra pasta, ou cliente aberto no meio do patch → Ao receber um ID de NPC ou de modelo desconhecido, pula → Só os NPCs adicionados recentemente ficam invisíveis em um dos lados - Sintomas: Invisível / entidade fantasma / Fatores: Perda de pacotes - Quem: Só um dos clientes no mesmo PC / Quando: Logo após login ou manutenção - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Cliente: enviar a versão dos dados ao conectar, registrar em log e mostrar um substituto ao receber IDs desconhecidos. Servidor: verificar a versão dos dados na conexão e, se for diferente, recusar a conexão e orientar o patch. - No gráfico: Alto só em alguns (IDs desconhecidos recebidos por versão do cliente) - Onde olhar: Comparar o caminho do executável dos dois clientes e as versões de cliente e de dados mostradas na tela e nos logs. No jogo, registrar a versão de dados enviada na conexão e quantas vezes IDs desconhecidos de NPC ou de modelo foram recebidos e pulados - Confirma se: Os dois clientes têm versões ou pastas de instalação diferentes, o NPC invisível foi adicionado em um patch recente, e ele aparece na instalação com o patch completo - Descarta se: Mesma versão e mesma pasta de instalação, mas falta só de um lado: aponta para “Diferença de canal, instância ou phasing” ou causas de carregamento ou de entrega - Como verificar: Verificação no ambiente do jogador - Fontes: - [NetworkConfig class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkConfig.html) · Unity · Com ProtocolVersion diferente, as pontas não se comunicam, e ForceSamePrefabs verifica na conexão diferenças na lista de prefabs #### pt-priority · Orçamento de envio e prioridade por conexão · Per-connection bandwidth budget and priority Se o servidor limita quanto envia por conexão e manda primeiro o que está mais perto, o lado com limite mais baixo recebe tarde, ou nunca recebe, os NPCs distantes. - Por quê → Efeito → Na tela: Em lugares lotados, o servidor envia por ordem de importância dentro do limite de envio de cada conexão → Uma conexão com estimativa de banda baixa (ex.: janela em segundo plano que confirma o recebimento tarde) continua adiando as entidades do fim da fila → NPCs distantes aparecem tarde ou não aparecem em um só lado - Sintomas: Invisível / entidade fantasma, Input lag / Fatores: Latência - Quem: Só um dos clientes no mesmo PC, Local ou canal específico / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: aumentar com o tempo a prioridade das entidades adiadas (para evitar starvation), garantir um intervalo mínimo de atualização. Cliente: enviar as confirmações de recebimento a tempo mesmo em segundo plano, para a estimativa de banda não cair. - No gráfico: Sobe com a carga (Entidades adiadas por conexão, volume enviado por conexão) - Onde olhar: Registrar no servidor, por conexão e por tick, os bytes enviados, o limite de envio (banda estimada), quantas entidades ficaram adiadas sem envio e quanto tempo passou desde o último envio de cada entidade. No Unreal, o Networking Insights mostra o tamanho dos pacotes por conexão e as entidades replicadas em cada um - Confirma se: O NPC invisível é uma entidade adiada há muito tempo nessa conexão, o limite dela é mais baixo que o das outras conexões, e as entidades adiadas aumentam quanto mais lotado o lugar - Descarta se: Sem entidades adiadas e com o NPC enviado a tempo: aponta para etapas depois do envio (buffer de recepção, carregamento, opções de exibição). Todas as conexões encostadas no limite: problema de volume de envio ou de design de visibilidade do servidor inteiro - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [Actor Priority in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-priority-in-unreal-engine) · Epic Games · Com a banda saturada, os atores a replicar são escolhidos por prioridade (distância, linha de visão, tempo desde a última replicação). Nem todos os atores são replicados toda vez - [State Synchronization](https://gafferongames.com/post/state_synchronization/) · Gaffer On Games · Acumulação de prioridade: entidades que não couberam neste pacote entram primeiro no próximo, e o limite de banda é ajustado em tempo real - [Networking Insights in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/networking-insights-in-unreal-engine) · Epic Games · Mostra, por conexão, o tamanho dos pacotes enviados e recebidos e as entidades e propriedades replicadas em cada um #### pt-clock-hold · Entidades retidas por erro na estimativa do relógio · Clock estimate error holds or discards entities Se o horário do servidor estimado pelo cliente está errado, ele retém informações de entidades que acabaram de chegar, como se fossem “do futuro”, ou as descarta como “antigas demais”. - Por quê → Efeito → Na tela: A estimativa do horário do servidor de um dos clientes erra muito (medida durante o carregamento, volta do modo de economia de energia) → O horário de referência da interpolação não bate com o horário das informações da entidade → A entidade aparece tarde ou fica parada - Sintomas: Invisível / entidade fantasma, Engasgos / Fatores: Latência - Quem: Só um dos clientes no mesmo PC / Quando: Depois de ficar parado, Logo após login ou manutenção - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Refazer a sincronização de horário periodicamente e redefinir na hora se a diferença for grande, não usar valores medidos durante o carregamento ou logo após voltar do modo de economia de energia. - No gráfico: Alto só em alguns (Erro na estimativa do horário do servidor por cliente) - Onde olhar: Registrar no cliente o horário do servidor estimado, o RTT, os momentos em que a sincronização de horário foi refeita e quantas vezes informações de entidades foram retidas ou descartadas. Tentar reproduzir logo após um carregamento ou logo após voltar do modo de economia de energia - Confirma se: Só no cliente com problema o erro de estimativa passa do limite de redefinição (no Unity, hardResetThresholdSec, padrão de 0,2 s), há registro de informações retidas como futuras ou descartadas como passadas, e refazer a sincronização de horário resolve na hora - Descarta se: Erro de estimativa pequeno, mas a entidade aparece tarde: aponta para “Orçamento de envio e prioridade por conexão” ou para o carregamento - Como verificar: Exige logs e métricas do servidor ou do cliente do jogo - Fontes: - [NetworkTimeSystem class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkTimeSystem.html) · Unity · Se a diferença de tempo passa de hardResetThresholdSec (padrão de 0,2 s), força o acerto; no resto do tempo, ajusta aos poucos com adjustmentRatio, acelerando ou desacelerando - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · LocalTime fica à frente do servidor, e ServerTime fica atrás. Mensagens que chegam tarde podem ter tempo de espera negativo ### Causas-raiz da retransmissão TCP (20 causas) #### rt-wireless · Perda no trecho sem fio · Wi-Fi / cellular link loss O Wi-Fi e a rede móvel tentam retransmitir algumas vezes no trecho sem fio e, se ainda assim não conseguem, descartam o pacote. O TCP só reenvia o pacote descartado bem mais tarde. - Por quê → Efeito → Na tela: Sinal fraco ou muita interferência fazem as transmissões no trecho sem fio falharem várias vezes seguidas → Passado o limite de tentativas do equipamento sem fio (normalmente de algumas a pouco mais de dez), o pacote é descartado → Trava enquanto o TCP espera para retransmitir; os pacotes seguintes ficam esperando no buffer de recepção e depois chegam em avanço rápido - Sintomas: Travamento, Avanço rápido, Teleporte / Fatores: Perda de pacotes, Jitter - Quem: Só eu, Mesma casa / Quando: Aleatoriamente, de vez em quando, Em movimento ou ao trocar de mapa - Responsável principal: Externo (Externo) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do servidor (Equipe de desenvolvimento), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: ligar o TCP_NODELAY (com o Nagle ligado, o RACK fica sem pacotes seguintes para usar na detecção de perda), enviar só a atualização de estado mais recente enquanto a retransmissão bloqueia o envio, sem acumular as anteriores (limitar com TCP_NOTSENT_LOWAT o volume acumulado no kernel). Cliente: ligar o TCP_NODELAY (as perdas no sentido dos comandos do jogador são recuperadas pelo SO do cliente), mostrar o estado da rede na tela quando as perdas se concentram ou o ping dispara. - O que fazer (Equipe de infraestrutura): Acelerar a recuperação de perdas com RACK-TLP (o servidor não consegue evitar a perda no sem fio, só recuperar mais rápido), confirmar que os padrões do Linux recente, net.ipv4.tcp_recovery=1 (RACK) e net.ipv4.tcp_early_retrans=3 (TLP), não foram alterados. - O que fazer (Externo): Orientar os jogadores a usar cabo, usar 5 GHz ou 6 GHz e mudar o roteador de lugar ou de canal. - Números de referência: Com 1% de perda no sem fio, 1 em cada 100 pacotes do jogo some. Recebendo 10 pacotes por segundo, há um engasgo a cada 10 segundos, em média. Sem RACK-TLP, cada perda deixa a conexão parada por um RTO (ping + pelo menos 200 ms). - No gráfico: Alto só em alguns (Taxa de retransmissão por conexão, RTT (ping) por conexão) - Onde olhar: No PC do jogador, enviar centenas de pings para o endereço do roteador (gateway) e para o servidor do jogo e comparar a perda e a variação da latência; repetir com cabo ou com dados móveis. No servidor, ver retrans e rtt (média/desvio) da conexão desse jogador com ss -ti - Confirma se: O ping até o roteador já mostra perda ou latência oscilando, e o problema some no cabo. No servidor, só a conexão desse jogador tem retrans e desvio de RTT altos - Descarta se: Limpo até o roteador, com perda a partir dele: operadora ou caminho (“Estouro de fila no gargalo”, “Mudança de rota ou caminho ECMP com defeito”). Vários jogadores da mesma operadora piorando ao mesmo tempo: verificar primeiro o trecho da operadora - Como verificar: Verificação no ambiente do jogador - Saiba mais: As tentativas do equipamento sem fio geram jitter (alguns ms a cada tentativa), e só viram perda quando passam do limite de tentativas. Por isso, conforme a qualidade do sem fio piora, os sintomas crescem nesta ordem: “jitter → travamentos ocasionais → travamentos frequentes”. No momento em que o dispositivo passa de um ponto de acesso (AP) para outro (roaming), pode haver perdas seguidas por um período de dezenas de ms a alguns segundos. A rede móvel retransmite muito no trecho até a antena, então o problema costuma aparecer mais como picos de latência de centenas de ms do que como perda. - Casos reais: ffxiv-2021 - Fontes: - [net/wireless/core.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/wireless/core.c?h=v6.12) · Linux kernel · Limites padrão de tentativas na pilha sem fio do Linux: 7 para frames curtos e 4 para frames longos (dot11ShortRetryLimit, dot11LongRetryLimit) - [RFC 3481: TCP over Second (2.5G) and Third (3G) Generation Wireless Networks](https://www.rfc-editor.org/rfc/rfc3481) · IETF · Na rede móvel, a retransmissão na camada de enlace mantém baixa a perda IP, mas essa recuperação aparece como jitter e picos de latência - [Wi-Fi roaming support in Apple devices](https://support.apple.com/guide/deployment/wi-fi-roaming-support-dep98f116c0f/web) · Apple · Ao trocar de AP, não dá para enviar dados até terminar a autenticação no novo AP; em ambientes 802.1X isso pode levar alguns segundos - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · Definição de RACK (detecção de perda por tempo) e TLP (retransmissão do último pacote) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_recovery com padrão 0x1 (RACK), tcp_early_retrans com padrão 3 (TLP ligado); TCP_NOTSENT_LOWAT e tcp_notsent_lowat limitam a quantidade de dados ainda não enviados - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_NODELAY desliga o algoritmo de Nagle e envia na hora até dados pequenos - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · Valor mínimo do RTO: TCP_RTO_MIN = 200 ms - [misc/ss.c](https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/misc/ss.c?h=v6.12.0) · iproute2 · ss -ti mostra retrans: retransmissões em andamento/total acumulado de retransmissões e rtt: RTT/desvio do RTT (rttvar) #### rt-queue-drop · Estouro de fila no gargalo (perda por congestionamento) · Tail drop at a congested bottleneck Quando enche a fila do ponto mais estreito do caminho (o roteador, a interconexão entre operadoras, o link do data center), os pacotes que chegam são descartados. - Por quê → Efeito → Na tela: Vídeo, downloads e o tráfego de outros usuários lotam o gargalo → Enquanto a fila está cheia, os pacotes que chegam são descartados um atrás do outro (tail drop). Os que escapam também esperam no fim da fila cheia → Vários pacotes somem de uma vez: um travamento longo e depois avanço rápido, com mais frequência à noite - Sintomas: Travamento, Avanço rápido, Rubber banding / Fatores: Perda de pacotes, Latência - Quem: Mesma casa, Região ou operadora específica, Servidor inteiro / Quando: Horário de pico à noite, Quando junta muita gente - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Externo (Externo), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Mostrar o estado da rede na tela quando as perdas se concentram ou o ping dispara (avisando que pode haver uma transferência grande na mesma conexão). - O que fazer (Equipe de infraestrutura): Manter folga nos links do data center, verificar os contadores de descarte de fila (output drops) dos nossos links e portas de switch, desviar por outro link ou peering quando o trecho da operadora estiver congestionado. - O que fazer (Externo): Orientar os jogadores a usar SQM no roteador (fq_codel, CAKE) e ECN (para reduzir a taxa antes de a fila estourar), pedir à operadora que amplie a capacidade do gargalo. - Números de referência: No momento em que a fila estoura, boa parte dos pacotes que chegam durante dezenas de ms some de uma vez. Como é fácil perder vários seguidos e perder também os reenvios, muitas vezes a recuperação só vem com o RTO. - No gráfico: Alto só em certos horários (Taxa de retransmissão, RTT (ping)) - Onde olhar: Taxa de retransmissão do servidor (incremento de TcpRetransSegs ÷ TcpOutSegs, rodando o nstat a cada 1 minuto) e RTT por conexão, separados por região, operadora e horário, junto com os descartes de saída (ifOutDiscards) dos nossos links e portas de switch. Rodar mtr até a região afetada no horário de pico e em um horário tranquilo e comparar - Confirma se: A taxa de retransmissão só sobe no pico da noite, e o RTT sobe antes da perda (a fila enchendo). No mtr, só no horário de pico a perda e a latência aumentam juntas de um trecho em diante até o destino - Descarta se: O RTT não sobe antes da perda: “Descarte do excedente pelo policer”. Perda parecida o tempo todo, sem relação com o horário: “Erros físicos” ou “Mudança de rota ou caminho ECMP com defeito” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Casos reais: riot-direct-2015 - Fontes: - [RFC 7567: IETF Recommendations Regarding Active Queue Management](https://www.rfc-editor.org/rfc/rfc7567) · IETF · Explicação de que o tail drop mantém a fila cheia por muito tempo, o que aumenta a latência e concentra as perdas, e recomendação de AQM - [RFC 8290: The Flow Queue CoDel Packet Scheduler and Active Queue Management Algorithm](https://www.rfc-editor.org/rfc/rfc8290) · IETF · fq_codel: filas por fluxo e AQM mantêm a fila curta e reduzem o bufferbloat - [RFC 3168: The Addition of Explicit Congestion Notification (ECN) to IP](https://www.rfc-editor.org/rfc/rfc3168) · IETF · ECN: sinaliza o congestionamento com uma marcação no cabeçalho IP, sem descartar o pacote - [Smart Queue Management](https://www.bufferbloat.net/projects/cerowrt/wiki/Smart_Queue_Management/) · Bufferbloat.net · SQM: combina escalonamento por fluxo, gerenciamento do tamanho da fila (AQM) e shaping - [Cake](https://www.bufferbloat.net/projects/codel/wiki/Cake/) · Bufferbloat.net · CAKE: SQM para roteadores que junta um shaper e um gerenciamento de fila da família fq_codel - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · TcpRetransSegs e TcpOutSegs no nstat (RetransSegs e OutSegs da seção Tcp) - [nstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/nstat.8.html) · iproute2 · Por padrão, o nstat mostra o incremento desde a execução anterior - [RFC 2863: The Interfaces Group MIB](https://www.rfc-editor.org/rfc/rfc2863) · IETF · ifOutDiscards: número de pacotes que, mesmo sem erro, foram descartados sem ser transmitidos, por motivos como liberar espaço no buffer - [An Internet-Wide Analysis of Traffic Policing](https://research.google/pubs/an-internet-wide-analysis-of-traffic-policing/) · Google · Diferença: no estouro de fila, o tempo de espera e o RTT sobem antes da perda; o policing descarta o excedente sem aumento do RTT (SIGCOMM 2016) #### rt-burst · Estouro de buffers rasos por bursts de envio · Sender bursts overflow shallow buffers Quando o servidor manda de uma vez, a cada tick, as atualizações de milhares de jogadores, o buffer pequeno do switch ou o limite instantâneo da nuvem estoura em menos de 1 ms, e parte dos pacotes é descartada. - Por quê → Efeito → Na tela: No início do tick, os pacotes para todos os jogadores saem de uma vez → O buffer da porta do switch que junta o tráfego de vários servidores (de centenas de KB a alguns MB por porta) ou o limite da instância na nuvem estoura por um instante (a utilização média é baixa) → Vários jogadores teleportam ou engasgam ao mesmo tempo, e as métricas de média não mostram a causa - Sintomas: Teleporte, Travamento, Avanço rápido / Fatores: Perda de pacotes - Quem: Local ou canal específico, Servidor inteiro / Quando: Quando junta muita gente - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Infraestrutura de rede (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Distribuir o envio de um tick ao longo do tick (o pacing por conexão não resolve bem milhares de conexões disparando no início do tick), espalhar o horário de início do tick entre os servidores, limitar a taxa com SO_MAX_PACING_RATE nas conexões que enviam muitos dados. - O que fazer (Equipe de infraestrutura): Servidores/SO: limitar a taxa de envio do servidor inteiro (shaper no SO do servidor, tc no Linux), suavizar com pacing (fila fq do Linux, BBR) os bursts de uma única conexão. Rede: switches com buffers maiores, verificar em intervalos curtos os contadores de descarte de saída das portas de switch (a utilização média não mostra o problema). - Números de referência: Uma porta de 10 Gbps envia cerca de 1,25 MB em 1 ms. Quando os ticks de vários servidores coincidem e convergem para uma porta, o buffer enche num instante. - No gráfico: Sobe com a carga (Descartes de saída na porta do switch, taxa de retransmissão) - Onde olhar: Coletar a cada poucos segundos os descartes de saída (ifOutDiscards) da porta do switch onde o servidor está ligado e da porta acima dela; na nuvem, ver bw_out_allowance_exceeded e pps_allowance_exceeded no ethtool -S. Coletar as retransmissões do mesmo momento com o tcpretrans do bcc e cruzar os dados - Confirma se: A utilização média por minuto é baixa, mas os descartes de saída ou os excessos de allowance aumentam, crescendo com o número de jogadores simultâneos e de jogadores reunidos em um só lugar. As retransmissões não se concentram em faixas de IP de jogadores (operadora, região) e acontecem no mesmo instante em várias conexões do servidor - Descarta se: Erros de CRC e de entrada subindo junto na mesma porta: “Erros físicos”. Contadores de descarte da NIC ou softnet dropped subindo no servidor que recebe: “Descarte de pacotes no servidor receptor” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O pacing atua em cada conexão separadamente. Milhares de conexões mandando um ou dois pacotes cada no início do tick formam um burst que o pacing por conexão não resolve bem; o servidor do jogo precisa distribuir ele mesmo os momentos de envio. Já quando uma conexão manda muitos dados, a NIC corta dezenas de KB em pacotes e os despeja em sequência (TSO), e o pacing distribui bem esse tipo de burst. - Fontes: - [High-Resolution Measurement of Data Center Microbursts](https://research.facebook.com/publications/high-resolution-measurement-of-data-center-microbursts/) · Meta · Mais de 70% dos bursts em switches de rack de data center terminam em dezenas de µs, e a relação entre a utilização média por minuto e os descartes é fraca (IMC 2017) - [tc-fq(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-fq.8.html) · iproute2 · A fila fq faz pacing por socket (conexão), e SO_MAX_PACING_RATE define a taxa máxima por conexão - [net/ipv4/tcp_bbr.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_bbr.c?h=v6.12) · Linux kernel · O BBR envia definindo o pacing_rate pela largura de banda estimada do gargalo - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · O TCP define o tamanho dos frames TSO conforme a taxa do fluxo (máximo de 64 KB, tcp_min_tso_segs) - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · bw_out_allowance_exceeded e pps_allowance_exceeded: número de pacotes enfileirados ou descartados por ultrapassar o limite de largura de banda ou de pacotes por segundo da instância - [RFC 2863: The Interfaces Group MIB](https://www.rfc-editor.org/rfc/rfc2863) · IETF · ifOutDiscards: número de pacotes que, mesmo sem erro, foram descartados sem ser transmitidos, por motivos como liberar espaço no buffer - [Demonstrations of tcpretrans, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/tcpretrans_example.txt) · IO Visor · Mostra uma linha por retransmissão, com endereço e porta remotos e o estado da conexão #### rt-policer · Descarte do excedente pelo policer · Traffic policing Planos de operadora, limites de instâncias na nuvem e equipamentos de proteção contra DDoS podem descartar na hora, sem colocar na fila, os pacotes que passam da taxa definida. - Por quê → Efeito → Na tela: O volume enviado em um instante passa da taxa ou do burst permitido → O excedente é descartado na hora, sem fila (policing) → Vários pacotes somem a cada burst grande: travamento e depois avanço rápido, enquanto a taxa média parece abaixo do limite - Sintomas: Travamento, Avanço rápido, Teleporte / Fatores: Perda de pacotes - Quem: Servidor inteiro, Região ou operadora específica, Só eu / Quando: Quando junta muita gente, Horário de pico à noite - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Distribuir ao longo do tick o que sai de uma vez a cada tick, para manter o volume instantâneo abaixo do burst permitido; se bater no limite de pacotes por segundo, juntar as mensagens de um tick em um só pacote. - O que fazer (Equipe de infraestrutura): Rede: verificar os contadores de excesso do policer nos equipamentos, usar shaper no lugar de policer, aumentar o burst permitido. Servidores/SO: verificar as métricas de excesso de limite da nuvem (na AWS, bw_out_allowance_exceeded e pps_allowance_exceeded no ethtool -S), subir o tipo da instância, fazer pacing no servidor (fila fq do Linux). - Números de referência: O shaper (que enfileira e atrasa) aumenta a latência; o policer (que descarta na hora) aumenta a perda. Uma conexão TCP de jogo pode ficar centenas de ms parada a cada perda, então, quando o limite é ultrapassado só por instantes, em geral o policer causa mais estrago. - No gráfico: Achata ao bater no limite (Volume enviado em intervalos curtos, contadores de excesso do policer e de allowance) - Onde olhar: Ver os contadores de excesso (exceed) e de descarte do equipamento onde está o policer; na nuvem, ver bw_out_allowance_exceeded e pps_allowance_exceeded no ethtool -S. Nas conexões com perda, ver o RTT logo antes da perda pelo rtt do ss -ti ou por captura de pacotes - Confirma se: Os contadores de excesso aumentam, e o volume enviado, visto em intervalos curtos, fica achatado como se fosse cortado em um valor. O RTT não sobe antes da perda, e vários pacotes somem de uma vez só nos momentos de burst grande - Descarta se: O RTT sobe antes da perda: estouro de fila (“Estouro de fila no gargalo”, “Estouro de buffers rasos por bursts de envio”). Contadores de excesso parados: outra causa - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 2475: An Architecture for Differentiated Services](https://www.rfc-editor.org/rfc/rfc2475) · IETF · Definição: o shaping atrasa os pacotes para adequá-los ao perfil de tráfego, e o policing descarta os pacotes que excedem o perfil - [An Internet-Wide Analysis of Traffic Policing](https://research.google/pubs/an-internet-wide-analysis-of-traffic-policing/) · Google · Transferências sob policing têm em média 6 vezes mais perda, e pacing ou shaping podem atingir o mesmo objetivo. Diferença: o policing descarta o excedente sem aumento do RTT, e no estouro de fila o RTT sobe antes da perda (SIGCOMM 2016) - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · bw_out_allowance_exceeded e pps_allowance_exceeded no ethtool -S: número de pacotes enfileirados ou descartados por ultrapassar o limite da instância - [tc-fq(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-fq.8.html) · iproute2 · Pacing por conexão na fila fq do Linux - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rtt no ss -i (tempo médio de ida e volta) #### rt-physical · Erros físicos (cabo, transceptor óptico ou conector com defeito) · Bit errors: bad cable, optics, dirty fiber Cabos danificados, conectores ópticos sujos e transceptores ópticos no fim da vida útil geram erros de bit, e os equipamentos descartam silenciosamente os pacotes corrompidos. - Por quê → Efeito → Na tela: Cabo, transceptor óptico ou conector com defeito inverte bits → O equipamento descarta os pacotes cujo checksum (CRC) não confere → Só quem passa por esse caminho tem, de forma constante, engasgos curtos seguidos de avanço rápido, sem relação com o horário - Sintomas: Travamento, Avanço rápido, Teleporte / Fatores: Perda de pacotes - Quem: Local ou canal específico, Mesma casa / Quando: Sempre - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Externo (Externo) - O que fazer (Equipe de infraestrutura): Os erros de CRC se acumulam na ponta que recebe no sentido com defeito, então verificar as duas pontas. Rede: verificar os contadores de erros de CRC e de entrada das portas dos equipamentos, checar a potência do sinal óptico (informações do transceptor no switch), limpar os conectores ópticos, trocar cabos e transceptores. Servidores/SO: verificar rx_crc_errors no ethtool -S do servidor (o nome varia um pouco conforme o driver), checar a potência do sinal óptico (ethtool -m), trocar o cabo ou a NIC do lado do servidor. - O que fazer (Externo): Se o problema estiver no trecho da casa do jogador, orientar a trocar o cabo de rede ou o roteador; se estiver no trecho da operadora, pedir à operadora que verifique a linha. - Números de referência: Mesmo 0,1% de perda é uma vez a cada 1.000 pacotes do jogo. Se dezenas de pessoas passam por esse caminho, alguém engasga a cada poucos segundos. Quanto maior o pacote, maior a chance de ele sofrer um erro de bit. - No gráfico: Alto só em alguns (Erros de CRC por porta, taxa de retransmissão por servidor e por porta) - Onde olhar: Ver os contadores de CRC nas duas pontas do link. No servidor, rx_crc_errors no ethtool -S ou crc no ip -s -s link; no switch, os erros de FCS (dot3StatsFCSErrors) e de entrada (ifInErrors) da porta. Em link óptico, ver a potência óptica recebida com ethtool -m e nas informações do transceptor no switch - Confirma se: Os erros de CRC de uma porta crescem de forma constante, em qualquer horário, e só os servidores e conexões que passam por essa porta têm taxa de retransmissão alta. A potência óptica recebida é menor que a de outros links do mesmo tipo - Descarta se: CRC parado e só os descartes de saída aumentando: estouro de fila (“Estouro de buffers rasos por bursts de envio”, “Estouro de fila no gargalo”). Colisões tardias de um lado e CRC do outro aumentando juntos: “Incompatibilidade de duplex” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · rx_crc_errors é o número de pacotes que a interface receptora contou como erro de CRC; visível com ip -s -s link e ethtool -S - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · -S mostra estatísticas por NIC e driver; -m mostra a EEPROM e as informações de diagnóstico óptico do transceptor (SFP+, QSFP) - [RFC 3635: Definitions of Managed Objects for the Ethernet-like Interface Types](https://www.rfc-editor.org/rfc/rfc3635) · IETF · Erros de FCS da porta do switch (dot3StatsFCSErrors), que entram na soma dos erros de entrada (ifInErrors) #### rt-duplex · Incompatibilidade de duplex · Duplex mismatch Quando um lado usa autonegociação e o outro tem velocidade e duplex fixos, um dos lados passa a operar em half-duplex e perde pacotes por colisão sempre que a carga aumenta. - Por quê → Efeito → Na tela: Só um dos equipamentos tem velocidade e duplex fixados na configuração → Um lado opera em full-duplex e o outro em half-duplex, com colisões e colisões tardias → Tudo normal até o tráfego aumentar; aí todos que passam por esse equipamento têm travamentos seguidos de avanço rápido - Sintomas: Travamento, Avanço rápido / Fatores: Perda de pacotes - Quem: Servidor inteiro, Local ou canal específico / Quando: Quando junta muita gente, Horário de pico à noite - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Usar autonegociação nos dois lados ou fixar o mesmo valor nos dois lados. Rede: verificar velocidade e duplex no estado da porta do switch e, nos contadores da porta, ver se aumentam as colisões tardias no lado half-duplex e os erros de CRC e os frames curtos demais (runts) no lado full-duplex. Servidores/SO: verificar velocidade e duplex com ethtool. - Números de referência: Em cabo de cobre de 1 Gbps a autonegociação é obrigatória, e a partir de 10 Gbps nem existe half-duplex. Por isso, hoje o problema aparece principalmente em equipamentos antigos de até 100 Mbps, em portas de gerência e em alguns trechos de interconexão de links. - No gráfico: Sobe com a carga (Colisões tardias e erros de CRC por porta, taxa de retransmissão) - Onde olhar: Ver a velocidade e o duplex reais nas duas pontas do link. No servidor, ethtool só com o nome da interface; no switch, o estado da porta ou dot3StatsDuplexStatus via SNMP. Ver também as colisões tardias (tx_window_errors no servidor, dot3StatsLateCollisions no switch) e os erros de CRC - Confirma se: Um lado aparece em half-duplex e o outro em full-duplex. Sempre que o tráfego aumenta, sobem juntos as colisões tardias no lado half-duplex e os erros de CRC no lado full-duplex - Descarta se: Velocidade e duplex iguais nos dois lados e só o CRC aumentando: “Erros físicos”. Links de 10 Gbps ou mais não têm half-duplex, então esta causa fica descartada - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Linux Base Driver for Intel(R) Ethernet Network Connection](https://docs.kernel.org/networking/device_drivers/ethernet/intel/e1000.html) · Linux kernel · A norma 1000BASE-T exige autonegociação - [IEEE 802.3ae 10 Gigabit Ethernet: HSSG Objectives](https://www.ieee802.org/3/ae/objectives.pdf) · IEEE · Ethernet de 10 gigabits só suporta full-duplex - [IEEE P802.3ba Objectives](https://www.ieee802.org/3/ba/PAR/P802.3ba_Objectives_0709.pdf) · IEEE · Ethernet de 40 e 100 gigabits também só suporta full-duplex - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · tx_window_errors é o número de transmissões que falharam por colisão tardia (late collision); rx_crc_errors é o número de pacotes recebidos com erro de CRC - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · speed, duplex e autoneg do ethtool -s configuram velocidade, duplex e autonegociação; só com o nome da interface, o ethtool mostra a configuração atual - [RFC 3635: Definitions of Managed Objects for the Ethernet-like Interface Types](https://www.rfc-editor.org/rfc/rfc3635) · IETF · dot3StatsDuplexStatus (mostra o duplex atual como halfDuplex ou fullDuplex), dot3StatsLateCollisions (número de colisões tardias) #### rt-host-drop · Descarte de pacotes no servidor receptor · Receiver host drops (ring, softirq, CPU) O pacote chega ao servidor, mas é descartado porque o ring buffer da NIC (o buffer que guarda por um momento os pacotes que chegam) estourou ou porque o núcleo que faz o processamento de recepção no kernel está saturado. - Por quê → Efeito → Na tela: Pico de jogadores, interrupções concentradas em um só núcleo, CPU steal na máquina virtual, switch virtual sobrecarregado → Descarte no ring buffer (rx_missed_errors e outros; o nome varia conforme o driver) ou na fila de recepção do kernel (softnet dropped) → Quando junta muita gente, os comandos demoram a responder e há engasgos no servidor inteiro ao mesmo tempo - Sintomas: Input lag, Travamento, Avanço rápido, Teleporte / Fatores: Perda de pacotes, Paralisação - Quem: Servidor inteiro / Quando: Quando junta muita gente - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Incluir no monitoramento os contadores de descarte como rx_missed_errors do ethtool -S e o dropped do /proc/net/softnet_stat, aumentar o ring buffer (ethtool -G), distribuir RSS e interrupções entre vários núcleos, separar a thread do jogo dos núcleos de processamento de recepção, manter folga de CPU, em máquina virtual verificar o CPU steal e a carga do switch virtual. - Números de referência: Os pacotes que o servidor descartou ao receber são reenviados pelo cliente. Por isso, quase não aparecem nas métricas de retransmissão do servidor e se mostram primeiro em contadores de descarte como rx_missed_errors no ethtool -S (o nome varia conforme o driver) e no dropped do /proc/net/softnet_stat. - No gráfico: Achata ao bater no limite (Uso de softirq por núcleo, contadores de descarte da NIC) - Onde olhar: Ver os contadores de descarte do ethtool -S (rx_missed_errors e outros; no mlx5, rx_out_of_buffer e rx_discards_phy), o missed do ip -s -s link e a 2ª coluna (dropped) e a 3ª coluna (time_squeeze) do /proc/net/softnet_stat, além do %soft (processamento de interrupções de software) por núcleo com mpstat -P ALL. Em máquina virtual, ver também o %steal - Confirma se: Nos horários de pico de jogadores, os contadores de descarte ou o softnet dropped aumentam, e o %soft do núcleo responsável pela recepção fica perto de 100% sem conseguir subir mais. Os comandos atrasam ao mesmo tempo em todas as conexões desse servidor - Descarta se: Contadores de descarte do servidor parados e retransmissões concentradas em conexões de uma região ou operadora: perda no caminho. Quando o caminho perde pacotes enviados pelo servidor, o TcpRetransSegs do nstat do servidor aumenta e esses contadores ficam parados - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · rx_missed_errors é o número de pacotes que o host não conseguiu receber por falta de buffer (no /proc/net/dev, entra na soma de drop); visível com ip -s -s link - [drivers/net/ethernet/intel/igb/igb_ethtool.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/intel/igb/igb_ethtool.c?h=v6.12) · Linux kernel · Os nomes dos contadores do ethtool -S são definidos pelo driver (ex.: rx_missed_errors e rx_no_buffer_count no igb) - [Ethtool counters](https://docs.kernel.org/networking/device_drivers/ethernet/mellanox/mlx5/counters.html) · Linux kernel · rx_out_of_buffer (fila de recepção sem buffer) e rx_discards_phy (descarte por falta de buffer na porta) no driver mlx5 - [net/core/net-procfs.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/core/net-procfs.c?h=v6.12) · Linux kernel · /proc/net/softnet_stat tem uma linha por CPU, em hexadecimal; a 2ª coluna é dropped e a 3ª é time_squeeze - [Documentation for /proc/sys/net/](https://docs.kernel.org/admin-guide/sysctl/net.html) · Linux kernel · netdev_max_backlog: limite da fila de recepção que acumula pacotes quando eles chegam mais rápido do que o kernel processa - [Scaling in the Linux Networking Stack](https://docs.kernel.org/networking/scaling.html) · Linux kernel · RSS: a NIC divide os pacotes entre várias filas de recepção, processadas por várias CPUs - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · -G (--set-ring) muda o tamanho do ring buffer - [proc_stat(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc_stat.5.html) · Linux man-pages · steal no /proc/stat: tempo em que outro SO usou a CPU em ambiente virtualizado - [mpstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/mpstat.1.html) · sysstat · mpstat -P ALL mostra a utilização por núcleo; %soft é o tempo de processamento de interrupções de software, e %steal é o tempo de espera enquanto o hipervisor atendia outra CPU virtual - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · TcpRetransSegs no nstat (RetransSegs da seção Tcp) #### rt-stateful-fw · Descarte pelo firewall ou pelo rastreamento de conexões · Stateful firewall / conntrack drops O firewall ou o rastreamento de conexões do Linux (conntrack, recurso que registra numa tabela as conexões que passam) descarta pacotes quando a tabela enche ou quando conclui que o estado da conexão não confere. - Por quê → Efeito → Na tela: Tabela de rastreamento de conexões cheia (table full), ou ida e volta por caminhos diferentes, com só um sentido passando pelo firewall (rota assimétrica) → O firewall trata os pacotes como de “conexão desconhecida” ou com “número de sequência fora da janela” e descarta → Com a tabela cheia, novas conexões são bloqueadas; com o caminho desencontrado, só quem passa por esse caminho sofre desconexão depois de retransmissões repetidas - Sintomas: Travamento, Desconexão, Não conecta / loading infinito / Fatores: Perda de pacotes - Quem: Servidor inteiro, Região ou operadora específica / Quando: Quando junta muita gente, Logo após login ou manutenção, Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do servidor (Equipe de desenvolvimento), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: para o caso de a tabela encher, controlar picos de conexão com um sistema de fila de login, reutilizar conexões para não abrir conexões curtas repetidamente (inclusive nas chamadas entre servidores), encerrar por conta própria as conexões cujo heartbeat parou. Cliente: se a conexão falhar ou cair, aumentar o intervalo entre tentativas e espalhá-las aleatoriamente (para não voltarem todos de uma vez quando a tabela estiver cheia). - O que fazer (Equipe de infraestrutura): Rede: aumentar a tabela de rastreamento de conexões do firewall, tirar as portas do jogo do rastreamento de conexões, ajustar o roteamento para que ida e volta passem pelo mesmo firewall, verificar a configuração de validação da janela TCP no firewall. Servidores/SO: aumentar a tabela no Linux (nf_conntrack_max), tirar as portas do jogo do rastreamento de conexões (NOTRACK), verificar a configuração de validação da janela TCP (nf_conntrack_tcp_be_liberal), na AWS verificar também conntrack_allowance_exceeded. - Números de referência: O limite padrão do conntrack no Linux (nf_conntrack_max) vai de dezenas de milhares a centenas de milhares de entradas, conforme a memória. Quando o número atual (nf_conntrack_count) chega ao limite, aparece no log “nf_conntrack: table full, dropping packet”. - No gráfico: Achata ao bater no limite (Entradas do conntrack (nf_conntrack_count), falhas de novas conexões) - Onde olhar: Em servidor Linux, ver nf_conntrack_count e nf_conntrack_max, “nf_conntrack: table full, dropping packet” no dmesg e drop e invalid em /proc/net/stat/nf_conntrack (uma linha por núcleo, em hexadecimal). No firewall, ver o uso da tabela de sessões e o log de descartes; na AWS, conntrack_allowance_exceeded no ethtool -S - Confirma se: O número de entradas encosta no limite e achata, e no mesmo momento aumentam o log de table full e o drop, ou o conntrack_allowance_exceeded. Com rota assimétrica, a tabela tem folga, mas invalid e o log de descartes do firewall aumentam nas conexões de um caminho específico - Descarta se: Entradas longe do limite e invalid e log de descartes parados: outra causa. Tabela com folga, mas CPU ou pacotes por segundo do firewall no máximo: “Sobrecarga de equipamento intermediário” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · O padrão de nf_conntrack_max é o número de buckets do hash (memória ÷ 16384, de 1.024 a 262.144); o número atual fica em nf_conntrack_count; com nf_conntrack_tcp_be_liberal, só RSTs fora da janela são tratados como INVALID - [net/netfilter/nf_conntrack_core.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_conntrack_core.c?h=v6.12) · Linux kernel · Quando a tabela enche, registra “nf_conntrack: table full, dropping packet” no log e descarta (a estatística drop aumenta); pacotes que não batem com o estado da conexão aumentam a estatística invalid - [iptables-extensions(8) — Linux manual page](https://man7.org/linux/man-pages/man8/iptables-extensions.8.html) · netfilter · CT --notrack na tabela raw exclui do rastreamento de conexões - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Ao passar do limite de conexões rastreadas por instância, os pacotes são descartados (visível em conntrack_allowance_exceeded), e a recomendação é evitar rotas assimétricas - [net/netfilter/nf_conntrack_standalone.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/netfilter/nf_conntrack_standalone.c?h=v6.12) · Linux kernel · /proc/net/stat/nf_conntrack tem uma linha por núcleo, em hexadecimal, com colunas como entries, invalid, insert_failed, drop e early_drop #### rt-appliance-pps · Sobrecarga de equipamento intermediário (firewall, IPS, proteção contra DDoS) · Inline appliance PPS / CPU overload Firewalls, sistemas de prevenção de intrusão (IPS) e equipamentos de proteção contra DDoS inspecionam um por um os pacotes que passam. Quando a carga passa da capacidade de inspeção, eles descartam os pacotes que não conseguem processar. - Por quê → Efeito → Na tela: Em horários de pico e eventos, chegam centenas de milhares de pequenos pacotes de jogo por segundo (ou mais), ou então as regras de inspeção são pesadas → O limite de CPU ou de pacotes por segundo do equipamento se esgota e ele descarta pacotes. Com falso positivo, bloqueia até pacotes legítimos → Travamentos e teleporte ao mesmo tempo em todos os servidores atrás desse equipamento, piorando só quando junta muita gente - Sintomas: Travamento, Avanço rápido, Teleporte, Desconexão / Fatores: Perda de pacotes, Latência - Quem: Servidor inteiro, Região ou operadora específica / Quando: Horário de pico à noite, Quando junta muita gente - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Compartilhar com a equipe de infraestrutura o padrão de tráfego do jogo (portas, tamanho dos pacotes, pacotes por segundo), juntar as mensagens pequenas de um tick e enviá-las de uma vez para reduzir o número de pacotes. - O que fazer (Equipe de infraestrutura): Acompanhar CPU, pacotes por segundo e contadores de descarte do equipamento junto com as métricas do jogo, dimensionar a capacidade do equipamento com base em pacotes pequenos, tirar as portas do jogo das inspeções pesadas, ajustar as regras de proteção contra DDoS ao padrão de tráfego do jogo. - Números de referência: Os “10 Gbps” da especificação do equipamento muitas vezes valem para pacotes grandes, de 1.500 bytes. Pacotes de jogo têm por volta de 100 bytes, o que dá mais de 10 vezes mais pacotes na mesma largura de banda; o limite de pacotes por segundo esgota primeiro, mesmo com o link parecendo ocioso. - No gráfico: Achata ao bater no limite (Pacotes por segundo e uso de CPU do equipamento, descartes no equipamento) - Onde olhar: Ver CPU, pacotes por segundo e contadores de descarte do equipamento e comparar, no mesmo intervalo, a contagem de pacotes nas portas de switch antes e depois dele. Sobrepor na mesma tela o número de jogadores simultâneos e a taxa de retransmissão dos servidores - Confirma se: Em picos e eventos, os pacotes por segundo ou a CPU do equipamento estacionam em um valor e não sobem mais, saem do equipamento menos pacotes do que entram, e no mesmo momento a taxa de retransmissão sobe em todos os servidores atrás dele - Descarta se: Mesma contagem de pacotes antes e depois do equipamento e sem descartes nele: outra causa. Contadores de descarte da NIC ou softnet dropped subindo no servidor: “Descarte de pacotes no servidor receptor” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 2544: Benchmarking Methodology for Network Interconnect Devices](https://www.rfc-editor.org/rfc/rfc2544) · IETF · O desempenho do equipamento deve ser testado com vários tamanhos de frame, incluindo o mínimo e o máximo (a capacidade de processamento muda com o tamanho do pacote) #### rt-mtu · Black hole de MTU (perda repetida só dos pacotes grandes) · PMTU black hole Se algum trecho do caminho passa a aceitar só pacotes menores e o aviso de “grande demais” (ICMP) é bloqueado, os pacotes grandes continuam sumindo, por mais vezes que sejam reenviados. - Por quê → Efeito → Na tela: O tamanho máximo diminui em um trecho de VPN ou túnel, e um firewall bloqueia os avisos de pacote grande demais → Sem saber o motivo, quem envia retransmite o mesmo pacote grande sem parar, e o RTO dobra a cada vez → Tudo normal até chegar um momento de dados grandes (inventário, lugar lotado, carregamento ao entrar); aí tudo para, até os pacotes pequenos que vêm depois, e no fim vem a desconexão ou o loading infinito - Sintomas: Travamento, Desconexão, Não conecta / loading infinito / Fatores: Perda de pacotes - Quem: Região ou operadora específica, Só eu / Quando: Ao fazer ações específicas, Logo após login ou manutenção - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Para reduzir direto no servidor, configurar o tamanho máximo de segmento do socket (TCP_MAXSEG); só dividir as mensagens em pedaços menores no código do jogo não evita o problema (o TCP junta de novo os dados a enviar em blocos do tamanho do MSS). - O que fazer (Equipe de infraestrutura): Rede: fazer MSS clamping nos equipamentos de borda, liberar o ICMP de pacote grande demais (tipo 3, código 4, fragmentation needed) nos firewalls e nas ACLs de rede da nuvem. Servidores/SO: configurar o MTU do caminho, verificar se o ICMP de pacote grande demais não é bloqueado também nos firewalls dos servidores e nos grupos de segurança da nuvem, usar o tcp_mtu_probing=1 do Linux como última rede de segurança. - Números de referência: Normalmente 1.500 bytes, cerca de 1.400 ao passar por um túnel. Se o mesmo pacote é retransmitido 5–6 vezes, a conexão fica mais de 10 segundos parada. - No gráfico: Alto só em alguns (RTO e backoff por conexão, desconexões por região e operadora) - Onde olhar: Ver as retransmissões da conexão com problema por captura de pacotes no servidor ou com bcc tcpretrans -s (mostra o número de sequência), e ver mss, pmtu e backoff dessa conexão com ss -ti. Do servidor, enviar ao endereço do jogador um ping pequeno e um ping de 1.500 bytes com DF (ping -M do -s 1472) e comparar - Confirma se: Pacotes cheios até o MSS são retransmitidos sem parar com o mesmo número de sequência, com o intervalo dobrando a cada vez, enquanto os pacotes menores passam. Não chega nenhum ICMP de pacote grande demais (filtro do Wireshark icmp.type == 3 and icmp.code == 4); o ping pequeno responde, e só o ping grande com DF some sem resposta - Descarta se: Pacotes pequenos também somem: perda sem relação com o tamanho (“Estouro de fila no gargalo”, “Mudança de rota ou caminho ECMP com defeito”). O ICMP de pacote grande demais chega e o pmtu do ss -ti diminui: a descoberta do MTU do caminho está funcionando - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Com tcp_mtu_probing=1, o kernel só conclui que há um black hole depois de alguns segundos de timeouts de retransmissão (o equivalente a tcp_retries1=3) e então reduz o MSS para 1.024 bytes. Durante esse tempo a conexão fica parada, então ele serve como última rede de segurança; a prioridade é o MSS clamping, que evita o problema antes. - Fontes: - [RFC 1191: Path MTU discovery](https://www.rfc-editor.org/rfc/rfc1191) · IETF · Descoberta do MTU do caminho: um pacote grande demais é sinalizado com o ICMP “fragmentation needed and DF set” (tipo 3, código 4) - [RFC 2923: TCP Problems with Path MTU Discovery](https://www.rfc-editor.org/rfc/rfc2923) · IETF · O problema do black hole de PMTU: com o ICMP bloqueado, só os pacotes grandes continuam sumindo - [RFC 4821: Packetization Layer Path MTU Discovery](https://www.rfc-editor.org/rfc/rfc4821) · IETF · Método em que a camada de transporte sonda o tamanho do pacote sem depender de ICMP (base do tcp_mtu_probing do Linux) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_mtu_probing: 0 desligado, 1 só quando um black hole é detectado, 2 sempre (MSS inicial em tcp_base_mss). tcp_retries1 com padrão 3 - [net/ipv4/tcp_timer.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_timer.c?h=v6.12) · Linux kernel · Quando as retransmissões por RTO se repetem tcp_retries1 vezes, o kernel considera detectado um black hole, liga a sondagem de MTU e reduz o MSS - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · TCP_BASE_MSS = 1.024 bytes - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · A cada expiração do timer de retransmissão, o RTO dobra - [iptables-extensions(8) — Linux manual page](https://man7.org/linux/man-pages/man8/iptables-extensions.8.html) · netfilter · TCPMSS --clamp-mss-to-pmtu: contorna o problema dos pacotes grandes que param em trechos que bloqueiam ICMP, ajustando o MSS no SYN - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_MAXSEG: tamanho máximo de segmento dos pacotes de saída; se definido antes da conexão, muda também o MSS anunciado ao outro lado - [Network maximum transmission unit (MTU) for your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html) · AWS · Internet gateways e VPNs com MTU de 1.500; o PMTUD precisa do ICMP tipo 3, código 4, que não chega se grupos de segurança ou ACLs de rede o bloquearem - [MTU considerations | Cloud VPN](https://cloud.google.com/network-connectivity/docs/vpn/concepts/mtu-considerations) · Google Cloud · MTU do gateway do Cloud VPN de 1.460 bytes, MTU de payload do túnel IPv4 de 1.406 bytes (cerca de 1.400 ao passar pelo túnel) - [Demonstrations of tcpretrans, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/tcpretrans_example.txt) · IO Visor · Mostra uma linha por retransmissão; -s mostra também o número de sequência do pacote retransmitido - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · mss, pmtu (MTU do caminho) e backoff (quantas vezes o RTO dobrou) no ss -i - [ping(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ping.8.html) · iputils · -M do liga o DF e não envia pacotes maiores que o MTU do caminho conhecido pelo kernel; -s é o tamanho dos dados (sem contar os 8 bytes do cabeçalho ICMP) - [Display Filter Reference: Internet Control Message Protocol](https://www.wireshark.org/docs/dfref/i/icmp.html) · Wireshark · Filtros de exibição icmp.type e icmp.code #### rt-mapping · Expiração do mapeamento NAT ou do load balancer no meio da conexão · NAT / load balancer mapping expired mid-connection Se um equipamento no caminho apaga o mapeamento de uma conexão ociosa (a entrada que diz para onde encaminhar essa conexão), o próximo pacote enviado não é entregue. A conexão fica só retransmitindo até cair, ou o equipamento devolve uma recusa (RST) e ela cai na hora. - Por quê → Efeito → Na tela: Uma conexão sem pacotes por um tempo (jogador ausente, lobby) → O NAT do roteador, o CGNAT da operadora, o firewall, o load balancer ou o grupo de segurança da nuvem apaga o mapeamento ocioso → Ao voltar a se mexer, vêm retransmissões seguidas e depois a desconexão, ou a desconexão é imediata - Sintomas: Desconexão, Travamento / Fatores: Perda de pacotes - Quem: Só eu, Região ou operadora específica / Quando: Depois de ficar parado - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Infraestrutura de rede (Equipe de infraestrutura), Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Cliente: enviar heartbeats em intervalos de no máximo metade do menor timeout de inatividade (o mapeamento do roteador do jogador e do CGNAT da operadora só é renovado com certeza por pacotes que saem de dentro, e não temos como mudar esse timeout, por isso quem envia é o cliente), reconectar automaticamente se cair. Servidor: responder aos heartbeats e encerrar por conta própria a conexão que passar um tempo sem recebê-los (reduzir o intervalo do keepalive TCP com opções de socket como TCP_KEEPIDLE, detectar rápido com TCP_USER_TIMEOUT), retomar a sessão com um token de sessão. - O que fazer (Equipe de infraestrutura): Rede: levantar os timeouts de inatividade dos firewalls e load balancers do caminho e compartilhar com a equipe de desenvolvimento, aumentar os dos nossos firewalls e load balancers se necessário. Servidores/SO: verificar o tempo de rastreamento de conexões do grupo de segurança da nuvem e compartilhar com a equipe de desenvolvimento. - Números de referência: O tempo que cada equipamento mantém um mapeamento TCP varia de alguns minutos a algumas horas. Quando o grupo de segurança da nuvem rastreia as conexões, nos tipos de instância AWS Nitro v6 a entrada de rastreamento é apagada por padrão após 350 segundos (nos outros tipos, 5 dias; veja “Expiração do rastreamento de conexões no grupo de segurança da nuvem”). O keepalive TCP do Linux tem como padrão “verificar após 2 horas de inatividade”, mais tarde que a maioria dos equipamentos. - No gráfico: Queda de conexões em massa (Desconexões, tempo ocioso antes da queda) - Onde olhar: Ver os últimos minutos das conexões que caíram por captura de pacotes no servidor e, nas conexões vivas, o tempo ocioso por lastsnd e lastrcv do ss -ti (ms desde o último envio e o último recebimento). Ver também TcpExtTCPAbortOnTimeout no nstat (conexões abandonadas porque o timer esgotou) - Confirma se: Em cada conexão que caiu, o tempo ocioso logo antes da queda passou de um valor parecido (o timeout de inatividade de um equipamento do caminho, ex.: 350 s do grupo de segurança em instâncias AWS Nitro v6), e, desde o primeiro pacote após a inatividade, só há retransmissões sem ACK até a desistência, ou um RST volta na hora - Descarta se: Cai também durante o jogo, sem relação com o tempo ocioso: outra causa (“Mudança de rota ou caminho ECMP com defeito”, “Descarte pelo firewall ou pelo rastreamento de conexões”). Conexão com heartbeat em intervalos de no máximo metade do menor timeout de inatividade: esta causa fica descartada - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 5382: NAT Behavioral Requirements for TCP](https://www.rfc-editor.org/rfc/rfc5382) · IETF · Recomendação de que o timeout de inatividade de conexões TCP no NAT seja de pelo menos 2 horas e 4 minutos (partindo do princípio de que os equipamentos podem apagar antes as sessões ociosas) - [RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP](https://www.rfc-editor.org/rfc/rfc4787) · IETF · O mapeamento NAT deve ser renovado por pacotes que saem de dentro (REQ-6), e a renovação por pacotes que chegam de fora é opcional (para UDP) - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Timeout padrão de rastreamento de TCP ocioso: 350 segundos nos tipos de instância Nitro v6 e 432.000 segundos (5 dias) nos demais. Recomenda-se keepalive em intervalos menores que 5 minutos - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_keepalive_time com padrão de 2 horas - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_KEEPIDLE (tempo ocioso antes de começar o keepalive), TCP_USER_TIMEOUT (tempo esperando a confirmação dos dados antes de fechar a conexão) - [RFC 5482: TCP User Timeout Option](https://www.rfc-editor.org/rfc/rfc5482) · IETF · Timeout de usuário do TCP: quanto tempo os dados enviados podem ficar sem confirmação antes de a conexão ser fechada - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · lastsnd e lastrcv no ss -i: tempo (ms) desde o último envio e o último recebimento - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPAbortOnTimeout: número de conexões abandonadas sem RST porque um timer do TCP esgotou #### rt-path · Mudança de rota ou caminho ECMP com defeito · Route change / bad ECMP member Pacotes somem durante os segundos em que a rota na internet muda, ou nas conexões que caíram em um caminho com defeito entre vários caminhos ECMP. - Por quê → Efeito → Na tela: Recálculo de rotas do BGP, ou defeito no equipamento ou link de um dos vários caminhos (ECMP, LAG) → Perda temporária durante a troca de rota, ou perda constante só nas conexões que passam por esse caminho → De repente trava por alguns segundos e depois vem o avanço rápido, ou “reconectei e melhorou” (caiu em outro caminho) - Sintomas: Travamento, Avanço rápido, Teleporte / Fatores: Perda de pacotes - Quem: Região ou operadora específica / Quando: Aleatoriamente, de vez em quando - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Externo (Externo) - O que fazer (Equipe de desenvolvimento): Registrar estatísticas de retransmissão por conexão (TCP_INFO), para poder extrair o IP, a porta e o horário de quem é afetado, não derrubar na hora uma conexão que ficou alguns segundos parada. - O que fazer (Equipe de infraestrutura): Monitorar a taxa de retransmissão por região e operadora, verificar se a reconexão muda o caminho, contratar links de várias operadoras, inspecionar links com defeito nos caminhos ECMP e LAG dos nossos equipamentos, medir os caminhos com a mesma porta TCP do jogo (mtr --tcp --port; como o caminho é definido por endereço e porta, o ping comum pode seguir outro caminho e dar resultado normal). - O que fazer (Externo): Reportar o caminho com defeito à operadora, anexando medições feitas com a mesma porta TCP e a comparação antes e depois da reconexão. - No gráfico: Degrau a partir de um momento (RTT (ping), taxa de retransmissão por região e operadora) - Onde olhar: Agrupar as retransmissões por conexão com bcc tcpretrans -c para extrair endereço e porta dos jogadores afetados, e rodar mtr com a mesma porta TCP do jogo (mtr -T -P PORT) do servidor para o jogador e do jogador para o servidor, comparando os resultados. Comparar também antes e depois da reconexão - Confirma se: A partir de um certo momento, o RTT de uma região ou operadora muda em degrau, com alguns segundos de perdas concentradas; ou, dentro da mesma operadora, só algumas conexões (combinações de endereço e porta) retransmitem de forma constante e melhoram ao reconectar. Às vezes o ping comum está normal e a perda só aparece no mtr TCP - Descarta se: Todas as conexões da operadora piorando juntas no pico da noite: “Estouro de fila no gargalo”. Só um jogador ruim, com perda já no ping até o roteador: “Perda no trecho sem fio” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Casos reais: cloudflare-2020 - Fontes: - [RFC 2991: Multipath Issues in Unicast and Multicast Next-Hop Selection](https://www.rfc-editor.org/rfc/rfc2991) · IETF · Com vários caminhos, é difícil confiar nos resultados de ferramentas de diagnóstico como ping e traceroute; explica o método de fixar o caminho pelo hash do fluxo - [RFC 2992: Analysis of an Equal-Cost Multi-Path Algorithm](https://www.rfc-editor.org/rfc/rfc2992) · IETF · O ECMP escolhe o próximo caminho pelo hash dos campos de cabeçalho que identificam o fluxo (o mesmo fluxo segue o mesmo caminho) - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_INFO: consulta o estado de cada socket (struct tcp_info) - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · -T (--tcp) usa TCP SYN no lugar de ICMP, e -P (--port) define a porta de destino - [Demonstrations of tcpretrans, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/tcpretrans_example.txt) · IO Visor · Mostra uma linha por retransmissão, com endereço e porta remotos; -c soma as retransmissões por fluxo #### rt-spurious-delay · Retransmissão espúria por pico de latência · Spurious RTO from delay spikes O pacote só chegou muito atrasado por um instante, sem se perder. Mesmo assim, se o atraso passa do RTO, quem envia considera o pacote perdido e retransmite. - Por quê → Efeito → Na tela: Bufferbloat, economia de energia do Wi-Fi, transição de estado do rádio móvel ou pausa da máquina virtual levam a latência momentânea a centenas de ms → O RTO expira primeiro e o pacote é retransmitido, e o original chega logo depois (quem recebe fica com uma cópia duplicada) → Travamento e avanço rápido vêm do próprio pico de latência. A retransmissão espúria quase não aumenta o travamento; só faz subir a métrica de retransmissão e acaba sendo confundida com perda - Sintomas: Travamento, Avanço rápido, Input lag / Fatores: Latência, Jitter - Quem: Só eu, Servidor inteiro / Quando: Aleatoriamente, de vez em quando, Depois de ficar parado - Responsável principal: Externo (Externo) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): No cliente Android 10 ou superior, pedir o modo Wi-Fi de baixa latência durante o jogo (Wi-Fi lock WIFI_MODE_FULL_LOW_LATENCY, que só vale com a tela ligada e o jogo em primeiro plano), para reduzir os picos de latência causados pela economia de energia. - O que fazer (Equipe de infraestrutura): Evitar instâncias do tipo burstable, não baixar demais o RTO mínimo, manter F-RTO e timestamps (tcp_frto, tcp_timestamps), ler as métricas de retransmissão junto com TCPSpuriousRTOs e TCPDSACKRecv do nstat para não confundi-las com perda. - O que fazer (Externo): Orientar os jogadores a usar SQM no roteador e desligar a economia de energia do Wi-Fi, para reduzir os próprios picos de latência. - Números de referência: O Linux detecta RTOs espúrios com F-RTO e pode desfazer a redução da taxa de envio. Confira pelo TCPSpuriousRTOs do nstat (vezes em que um RTO foi considerado espúrio) e pelo TCPDSACKRecv (vezes em que quem recebe avisou que “já tinha recebido”). - No gráfico: Picos aleatórios (RTT (ping), RTOs espúrios) - Onde olhar: Rodar o nstat a cada 1 minuto e ver juntos os incrementos de TcpExtTCPTimeouts (expirações do RTO), TcpExtTCPSpuriousRTOs, TcpExtTCPDSACKRecv e TcpExtTCPLostRetransmit. Com captura de pacotes, usar o filtro do Wireshark tcp.analysis.spurious_retransmission - Confirma se: Quando os RTOs aumentam, TcpExtTCPSpuriousRTOs ou TcpExtTCPDSACKRecv sobem junto, e no mesmo momento o RTT dispara para centenas de ms. Na captura do lado que recebe, chegaram tanto o original quanto a retransmissão - Descarta se: TcpExtTCPSpuriousRTOs e DSACK parados, mas TcpExtTCPLostRetransmit (perda até do que foi reenviado) aumentando: perda real. RTT sem picos, mas DSACK alto de forma constante: “Retransmissão rápida espúria por pacotes fora de ordem” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 5682: Forward RTO-Recovery (F-RTO): An Algorithm for Detecting Spurious Retransmission Timeouts with TCP](https://www.rfc-editor.org/rfc/rfc5682) · IETF · F-RTO: usa os ACKs que chegam depois do RTO para saber se o RTO foi espúrio - [RFC 3481: TCP over Second (2.5G) and Third (3G) Generation Wireless Networks](https://www.rfc-editor.org/rfc/rfc3481) · IETF · Os picos de latência da rede móvel (handover, recuperação do link etc.) causam timeouts e retransmissões espúrias no TCP e redução da janela de congestionamento - [RFC 2883: An Extension to the Selective Acknowledgement (SACK) Option for TCP](https://www.rfc-editor.org/rfc/rfc2883) · IETF · DSACK: quem recebe avisa sobre o recebimento duplicado, e quem envia fica sabendo que a retransmissão foi espúria - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPSpuriousRTOs (RTOs espúrios detectados pelo F-RTO), TcpExtTCPDSACKRecv (DSACKs recebidos), TcpExtTCPLostRetransmit (vezes em que o SACK indicou que um pacote reenviado se perdeu de novo) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_frto ligado por padrão (bom para redes sem fio com RTT instável), tcp_timestamps com padrão 1 - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · Base para afirmar que evitar retransmissões espúrias exige um RTO mínimo grande (recomenda pelo menos 1 segundo) - [WifiManager](https://developer.android.com/reference/android/net/wifi/WifiManager#WIFI_MODE_FULL_LOW_LATENCY) · Android (Google) · WIFI_MODE_FULL_LOW_LATENCY (API 29, Android 10): Wi-Fi lock de baixa latência que só vale com conexão a um AP, tela ligada e app em primeiro plano - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nomes dos contadores no nstat: TCPTimeouts, TCPSpuriousRTOs, TCPDSACKRecv, TCPLostRetransmit - [net/ipv4/tcp_timer.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_timer.c?h=v6.12) · Linux kernel · TCPTimeouts aumenta quando o timer de retransmissão (RTO) expira - [nstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/nstat.8.html) · iproute2 · Por padrão, o nstat mostra o incremento desde a execução anterior - [Display Filter Reference: Transmission Control Protocol](https://www.wireshark.org/docs/dfref/t/tcp.html) · Wireshark · Filtro de exibição tcp.analysis.spurious_retransmission #### rt-reorder · Retransmissão rápida espúria por pacotes fora de ordem · Reordering triggers spurious fast retransmit Quando a ordem dos pacotes muda ao passar por vários caminhos ou links agregados, quem recebe avisa com ACKs duplicados que “falta um pacote”, e quem envia reenvia um pacote que tinha chegado sem problema. - Por quê → Efeito → Na tela: Equipamentos que dividem o caminho pacote a pacote, LAGs (agregação de links) que distribuem pacote a pacote e o momento da troca de rota embaralham a ordem → Um pacote posterior chega antes e se acumulam 3 ACKs duplicados → retransmissão rápida → Os pacotes de jogo, esparsos, quase não são afetados. As atualizações grandes em lugares lotados e o download de patches ficam lentos, com engasgos de vez em quando - Sintomas: Engasgos, Input lag / Fatores: Jitter - Quem: Região ou operadora específica, Servidor inteiro / Quando: Sempre, Quando junta muita gente - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Rede: distribuir por conexão (ECMP e LAG com hash de endereço e porta), sem dividir pacote a pacote. Servidores/SO: usar RACK (detecção de perda por tempo, resistente a pacotes fora de ordem; quando detecta retransmissão espúria via DSACK, aumenta sozinho a tolerância a pacotes fora de ordem), verificar o grau de desordem que o Linux estima automaticamente para cada conexão (valor reordering no ss -ti, inicial tcp_reordering=3). - No gráfico: Sempre alto desde o início (Detecções de pacotes fora de ordem, DSACKs recebidos) - Onde olhar: Ver TcpExtTCPSACKReorder e TcpExtTCPTSReorder (vezes em que se detectaram pacotes fora de ordem) e TcpExtTCPDSACKRecv no nstat e, por conexão, reordering (aparece quando é diferente de 3) e reord_seen no ss -ti. Na captura de pacotes, usar o filtro do Wireshark tcp.analysis.out_of_order - Confirma se: Os contadores de pacotes fora de ordem e de DSACK sobem de forma constante, sem relação com o horário, e o valor reordering das conexões que passam por um caminho ou equipamento específico está acima de 3. Na captura do lado que recebe, o pacote posterior chega antes e o anterior chega logo em seguida - Descarta se: Contadores de pacotes fora de ordem parados e TcpExtTCPLostRetransmit aumentando: perda real. DSACK subindo só nos momentos de pico de RTT: “Retransmissão espúria por pico de latência” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 2991: Multipath Issues in Unicast and Multicast Next-Hop Selection](https://www.rfc-editor.org/rfc/rfc2991) · IETF · Dividir o caminho pacote a pacote muda a ordem, e, quando 3 ou mais pacotes posteriores chegam antes, o TCP faz uma retransmissão rápida espúria - [RFC 2992: Analysis of an Equal-Cost Multi-Path Algorithm](https://www.rfc-editor.org/rfc/rfc2992) · IETF · ECMP que escolhe o caminho pelo hash dos campos de cabeçalho que identificam o fluxo (distribuição por fluxo) - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Retransmissão rápida no terceiro ACK duplicado - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · O RACK detecta perdas por tempo e por isso resiste a pacotes fora de ordem; ao receber DSACK, aumenta o tempo de tolerância à desordem (reo_wnd) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · Valor inicial de tcp_reordering 3 (ajustado automaticamente por conexão até tcp_max_reordering), configuração do RACK em tcp_recovery - [misc/ss.c](https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/misc/ss.c?h=v6.12.0) · iproute2 · ss -ti mostra reordering:valor quando o reordering da conexão é diferente do padrão 3, e reord_seen:vezes quando a conexão já viu pacotes fora de ordem - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPSACKReorder e TcpExtTCPTSReorder (detecção de pacotes fora de ordem), TcpExtTCPDSACKRecv (DSACKs recebidos), TcpExtTCPLostRetransmit (pacote reenviado perdido de novo) - [include/uapi/linux/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/tcp.h?h=v6.12) · Linux kernel · tcpi_reord_seen no tcp_info: quantas vezes a conexão viu pacotes fora de ordem - [Display Filter Reference: Transmission Control Protocol](https://www.wireshark.org/docs/dfref/t/tcp.html) · Wireshark · Filtro de exibição tcp.analysis.out_of_order #### rt-ack-path · ACKs atrasados ou perdidos (upload saturado) · ACK path congestion on asymmetric links Os dados chegaram bem, mas, se o ACK de “recebido” atrasa ou se perde na fila de upload lotada, quem envia considera o pacote perdido e retransmite. - Por quê → Efeito → Na tela: Upload de vídeo ou backup na nuvem em casa lota o upload → Os ACKs atrasam centenas de ms na fila do roteador ou são descartados quando ela estoura → Os pacotes de jogo que o servidor envia em geral chegam na hora. Seus comandos, presos na mesma fila de upload, atrasam: input lag, rubber banding e, às vezes, retransmissões espúrias - Sintomas: Input lag, Rubber banding / Fatores: Latência, Perda de pacotes - Quem: Mesma casa / Quando: Aleatoriamente, de vez em quando, Horário de pico à noite - Responsável principal: Externo (Externo) / Também envolvidos: Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Mostrar o estado da rede na tela quando o ping disparar, com o aviso “verifique programas fazendo upload”. - O que fazer (Externo): Orientar os jogadores a encurtar a fila de upload com SQM no roteador, priorizar pacotes pequenos (ACKs) e limitar a velocidade de upload (upload de vídeo, backup na nuvem). - Números de referência: Um ACK posterior confirma também os anteriores, então perder alguns ACKs em geral não causa problema. O problema é o atraso na fila. - No gráfico: Alto só em alguns (RTT (ping) por conexão) - Onde olhar: No PC do jogador, comparar o ping até o servidor do jogo com o upload (upload de vídeo, backup na nuvem) ligado e desligado. No servidor, ver o rtt da conexão desse jogador com ss -ti - Confirma se: Só durante o upload o ping sobe para centenas de ms e aparecem input lag e rubber banding; parando o upload, tudo volta logo. No servidor, o rtt dessa conexão também sobe nesse momento - Descarta se: Perda e latência sem relação com o upload: “Perda no trecho sem fio” ou causa no caminho. Só o sentido servidor → jogador atrasado, sem relação com o upload: “Estouro de fila no gargalo” - Como verificar: Verificação no ambiente do jogador - Fontes: - [RFC 3449: TCP Performance Implications of Network Path Asymmetry](https://www.rfc-editor.org/rfc/rfc3449) · IETF · Em links assimétricos com upload estreito, ACKs atrasados ou perdidos derrubam o desempenho do TCP; como o ACK é cumulativo, um ACK posterior cobre os que se perderam; contramedidas como escalonamento com prioridade para ACKs - [Smart Queue Management](https://www.bufferbloat.net/projects/cerowrt/wiki/Smart_Queue_Management/) · Bufferbloat.net · Manter a fila curta no roteador com gerenciamento de fila e shaping - [tc-cake(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-cake.8.html) · iproute2 · O CAKE separa os fluxos e minimiza a latência dos fluxos esparsos (sparse flows) - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rtt (tempo médio de ida e volta) e rttvar (desvio) no ss -i #### rt-rto-setting · Configuração de RTO inadequada para o ambiente · RTO min too low or too high Com o RTO mínimo baixo demais, qualquer pequeno atraso gera retransmissões espúrias; já o padrão (200 ms) é longo demais para um jogo, e cada perda deixa a conexão parada por muito tempo. - Por quê → Efeito → Na tela: RTO mínimo muito reduzido pensando no data center, ou o padrão mantido no trecho da internet → Baixo demais: avalanche de retransmissões até com picos momentâneos de latência. Alto demais: longa espera a cada perda → Com o padrão, cada perda causa um travamento de centenas de ms e depois avanço rápido; baixando demais, os travamentos diminuem, mas as retransmissões espúrias disparam e desperdiçam o link - Sintomas: Travamento, Avanço rápido, Input lag / Fatores: Latência - Quem: Servidor inteiro / Quando: Sempre - Responsável principal: Infraestrutura de servidores (Equipe de infraestrutura) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): No Linux 6.15 ou superior, avaliar baixar o teto do RTO das conexões do jogo com TCP_RTO_MAX_MS (o tempo até desistir também encurta, então definir junto, com TCP_USER_TIMEOUT, o tempo para considerar a conexão caída), baixar o RTO mínimo só nas conexões internas entre servidores com a opção de socket TCP_RTO_MIN_US (6.15 ou superior), avaliar a opção de socket TCP_THIN_LINEAR_TIMEOUTS para que, só nas conexões do jogo, RTOs seguidos não dobrem. - O que fazer (Equipe de infraestrutura): Baixar o rto_min por rota só nas conexões internas entre servidores; no trecho da internet, manter o padrão e compensar com RACK-TLP e a configuração de thin stream (tcp_thin_linear_timeouts). - Números de referência: RTO no Linux = tempo de ida e volta + max(200 ms, desvio do RTT × 4). Dobra a cada falha, até 120 segundos. A partir do Linux 6.15, dá para baixar esse teto para até 1 segundo com TCP_RTO_MAX_MS. - No gráfico: Sempre alto desde o início (RTO por conexão, RTOs espúrios) - Onde olhar: Ver a configuração de RTO mínimo do servidor (rto_min no ip route show; no Linux 6.11 ou superior, sysctl net.ipv4.tcp_rto_min_us), rto e rtt no ss -ti e o incremento de TcpExtTCPSpuriousRTOs no nstat - Confirma se: No servidor com mínimo reduzido, o rto das conexões pela internet fica colado no rtt, e TcpExtTCPSpuriousRTOs cresce muito. Com o padrão, o rto das conexões do jogo fica pelo menos 200 ms acima do rtt, e cada perda deixa a conexão parada por esse tempo - Descarta se: rto conforme o cálculo padrão (rtt + cerca de 200 ms) e poucos RTOs espúrios, mas paradas longas demais: perdas seguidas ou forma de recuperação (“Recuperação lenta em thin streams”, “Remoção de opções TCP por equipamento intermediário”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · RTO = SRTT + max(G, 4·RTTVAR), recomendação de mínimo de 1 segundo, dobra a cada falha, e um eventual máximo deve ser de pelo menos 60 segundos - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · No Linux, TCP_RTO_MIN de 200 ms e TCP_RTO_MAX de 120 segundos - [net/ipv4/tcp_input.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_input.c?h=v6.12) · Linux kernel · No Linux, o RTO é SRTT + rttvar, e o rttvar não fica abaixo do RTO mínimo (padrão de 200 ms) - [tcp: add the ability to control max RTO](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=54a378f43425085d0684679d99735696b69165bc) · Linux kernel · Inclusão da opção de socket TCP_RTO_MAX_MS (1–120 s), a partir do Linux 6.15 - [tcp: add sysctl_tcp_rto_min_us](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f086edef71be7174a16c1ed67ac65a085cda28b1) · Linux kernel · Inclusão de tcp_rto_min_us, RTO mínimo padrão para o servidor inteiro, a partir do Linux 6.11 - [tcp: support TCP_RTO_MIN_US for set/getsockopt use](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f38805c5d26fe4af97837c10d58074a7496638bf) · Linux kernel · Inclusão da opção de socket TCP_RTO_MIN_US, que define o RTO mínimo por socket, a partir do Linux 6.15 - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rto_min_us com padrão 200000 (a opção de rota rto_min e a opção de socket TCP_RTO_MIN_US têm prioridade), tcp_rto_max_ms de 1.000 a 120.000 (padrão 120.000), tcp_thin_linear_timeouts - [ip-route(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ip-route.8.html) · iproute2 · Opção rto_min por rota: o RTO mínimo na comunicação com aquele destino - [Thin-streams and TCP](https://docs.kernel.org/networking/tcp-thin.html) · Linux kernel · Com TCP_THIN_LINEAR_TIMEOUTS, dá para desligar o backoff exponencial só nas conexões thin stream - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_USER_TIMEOUT: tempo esperando a confirmação dos dados até fechar a conexão - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rto (ms) e rtt no ss -i - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPSpuriousRTOs: RTOs espúrios detectados pelo F-RTO #### rt-thin · Recuperação lenta em thin streams · Thin streams fall back to RTO Quando o jogo manda pacotes pequenos e espaçados, o RTO chega antes de se juntarem os “3 pacotes seguintes”. Com a mesma perda, a conexão fica parada por muito mais tempo do que em uma transferência grande. - Por quê → Efeito → Na tela: Com intervalo de cerca de 100 ms entre pacotes, há poucos pacotes ainda sem ACK (in flight) → Juntar 3 ACKs duplicados leva mais de 300 ms, então o RTO (ping + 200 ms) dispara antes; com perdas seguidas, ele dobra a cada vez → Cada perda trava o jogo por cerca de 0,3 s; se até o reenvio se perde, trava perto de 1 segundo e depois vem o avanço rápido - Sintomas: Travamento, Avanço rápido / Fatores: Perda de pacotes, Paralisação - Quem: Só eu, Servidor inteiro / Quando: Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: ligar o TCP_NODELAY (com o Nagle ligado, o RACK fica sem pacotes seguintes para a detecção), mandar os pacotes em tempo real por UDP, com retransmissão própria. Cliente: ligar o TCP_NODELAY, mandar os pacotes em tempo real do mesmo jeito que o servidor (UDP). - O que fazer (Equipe de infraestrutura): Usar RACK-TLP (padrão no Linux recente), usar tcp_thin_linear_timeouts para que RTOs seguidos não dobrem. - Números de referência: Com intervalo de 100 ms entre pacotes e ping de 60 ms, a retransmissão rápida leva cerca de 360 ms (até chegarem 3 pacotes seguintes e voltar a confirmação deles), e o RTO cerca de 260 ms. Com RACK, o reenvio acontece logo, por volta de 160 ms, quando volta a confirmação do pacote seguinte. Com intervalo acima de 200 ms entre pacotes, nem o RACK é mais rápido que o RTO. - No gráfico: Lacuna e depois tudo junto (Volume recebido por conexão, expirações de RTO) - Onde olhar: Comparar os incrementos de TcpExtTCPTimeouts (expirações do RTO), TcpExtTCPFastRetrans (retransmissão rápida), TcpExtTCPLossProbes e TcpExtTCPLossProbeRecovery (TLP) no nstat, e ver rto e backoff das conexões do jogo com ss -ti. Verificar também os valores de net.ipv4.tcp_recovery, tcp_early_retrans e tcp_sack no servidor - Confirma se: Entre as retransmissões, há mais expirações de RTO que retransmissões rápidas, e é comum ver backoff maior que 0 (passando por RTO) nas conexões do jogo. Durante a parada, o volume recebido fica em 0 e, quando a conexão se recupera, tudo chega de uma vez - Descarta se: Transferências grandes do mesmo servidor também ficam paradas por muito tempo: problema de perda sem relação com o perfil da conexão. Concentrado em conexões sem SACK e timestamps: “Remoção de opções TCP por equipamento intermediário” - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: O Linux já teve uma opção para thin streams que retransmitia com 1 ACK duplicado (tcp_thin_dupack), mas ela foi removida em 2017, e hoje o RACK cumpre esse papel. Com o Nagle ligado (TCP_NODELAY desligado), enquanto espera a confirmação do pacote perdido a conexão também não envia pacotes novos; o RACK fica sem pacotes seguintes para a detecção, e é preciso esperar o RTO. - Fontes: - [Thin-streams and TCP](https://docs.kernel.org/networking/tcp-thin.html) · Linux kernel · Thin streams como os de jogos, que enviam de forma esparsa, não se dão bem com a retransmissão rápida e dependem de timeouts longos; o critério é ter menos de 4 pacotes ainda sem ACK (in flight) - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Retransmissão rápida no terceiro ACK duplicado - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · O RACK detecta a perda quando um pacote enviado depois foi entregue; a espera do TLP é 2·SRTT (com uma folga para o ACK atrasado quando só há um pacote sem confirmação) - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · TCP_RTO_MIN de 200 ms, critério de thin stream (menos de 4 pacotes in flight) e 6 tentativas lineares - [tcp: remove thin_dupack feature](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4a7f6009441144783e5925551c72e3f2e1b0839b) · Linux kernel · Remoção do thin_dupack em janeiro de 2017 (Linux 4.11), com a explicação de que o RACK cumpre esse papel - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_thin_linear_timeouts: em thin streams, deixa de dobrar o RTO por até 6 tentativas (desligado por padrão) - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_NODELAY desliga o algoritmo de Nagle - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nomes dos contadores no nstat: TCPTimeouts, TCPFastRetrans, TCPLossProbes, TCPLossProbeRecovery - [net/ipv4/tcp_timer.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_timer.c?h=v6.12) · Linux kernel · TCPTimeouts aumenta quando o timer de retransmissão (RTO) expira - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPFastRetrans (retransmissões fora do estado Loss), TcpExtTCPLossProbes (TLPs enviados), TcpExtTCPLossProbeRecovery (perdas recuperadas por TLP) - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rto (ms) e backoff (quantas vezes o RTO dobrou) no ss -i #### rt-sack-stripped · Remoção de opções TCP por equipamento intermediário · Middlebox strips TCP options Quando alguns firewalls ou equipamentos de aceleração apagam ou alteram opções do TCP, a conexão fica lenta: ao perder vários pacotes, ela recupera só um por ida e volta, ou a janela (quanto dá para enviar de uma vez) fica pequena. - Por quê → Efeito → Na tela: A “normalização TCP” do firewall ou um equipamento de aceleração antigo remove as opções SACK, timestamps e window scaling → Com vários pacotes perdidos, a recuperação é de um por ida e volta, e a janela fica limitada a 64 KB → Cada perda trava o jogo por muito mais tempo (sem SACK, nem o RACK-TLP funciona) e, quando destrava, vem o avanço rápido. Transferências grandes, como patches, também ficam lentas - Sintomas: Travamento, Avanço rápido / Fatores: Paralisação, Latência - Quem: Região ou operadora específica, Servidor inteiro / Quando: Sempre - Responsável principal: Infraestrutura de rede (Equipe de infraestrutura) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de infraestrutura): Rede: desligar a normalização TCP no equipamento em questão, verificar também a randomização de números de sequência do firewall, comparar as opções do SYN em capturas de pacotes nas duas pontas. Servidores/SO: verificar no ss -ti se as conexões sem sack e wscale se concentram em um caminho específico (PCs com Windows podem não usar ts, conforme a configuração, então faltar só o ts pode ser normal), verificar se o net.ipv4.tcp_sack do servidor está em 1. - No gráfico: Sempre alto desde o início (Recuperações iniciadas sem SACK (TcpExtTCPRenoRecovery)) - Onde olhar: Ver no ss -ti se cada conexão mostra sack e wscale e, no nstat, a proporção entre TcpExtTCPRenoRecovery (recuperação iniciada sem SACK) e TcpExtTCPSackRecovery, além de TcpExtTCPSACKDiscard (blocos SACK descartados por incoerência). No caminho suspeito, capturar o SYN nas duas pontas e comparar as opções (tcp.options.sack_perm no Wireshark, entre outras) - Confirma se: Só as conexões que passam por um caminho ou equipamento específico estão sem sack e wscale, e a parcela de TcpExtTCPRenoRecovery é alta. A opção de SACK permitido que estava no SYN enviado não aparece no SYN recebido. Se a causa for a randomização de números de sequência, as opções continuam lá, mas TcpExtTCPSACKDiscard aumenta - Descarta se: Todas as conexões sem sack: verificar primeiro o valor de net.ipv4.tcp_sack do servidor. Opções intactas e TcpExtTCPSACKDiscard parado: a recuperação lenta tem outro motivo (“Recuperação lenta em thin streams”) - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Saiba mais: Mesmo com as opções presentes, o SACK pode quebrar. Se a randomização de números de sequência (sequence randomization) do firewall muda só o número de sequência do cabeçalho e deixa como estão os números dentro do SACK, quem envia descarta os SACKs incoerentes. O resultado é o mesmo quando, na falha de segurança do SACK em 2019, o SACK foi desligado no servidor com tcp_sack=0 e ficou esquecido assim. - Fontes: - [RFC 2018: TCP Selective Acknowledgment Options](https://www.rfc-editor.org/rfc/rfc2018) · IETF · Sem SACK, só com o ACK cumulativo, dá para saber de apenas um pacote perdido por ida e volta - [RFC 7323: TCP Extensions for High Performance](https://www.rfc-editor.org/rfc/rfc7323) · IETF · Sem a opção de window scaling, a janela é de no máximo 2^16 = 64 KiB - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · O RACK-TLP exige o uso de SACK - [net/ipv4/tcp_output.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_output.c?h=v6.12) · Linux kernel · No Linux, o TLP só é agendado em conexões que usam SACK - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_sack com padrão 1 (ligado) - [misc/ss.c](https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/misc/ss.c?h=v6.12.0) · iproute2 · ss -ti mostra ts, sack e wscale:envio,recepção conforme as opções que a conexão usa - [tcp: limit payload size of sacked skbs](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3b4929f65b0d8249f19a50245cd88ed1a2f78cff) · Linux kernel · Commit que corrige a vulnerabilidade de 2019 no tratamento de SACK (CVE-2019-11477) - [Linux and FreeBSD Kernel: Multiple TCP-based remote denial of service vulnerabilities (NFLX-2019-001)](https://raw.githubusercontent.com/Netflix/security-bulletins/master/advisories/third-party/2019-001.md) · Netflix · Na época, a medida provisória recomendada foi tcp_sack=0 (desligar o tratamento de SACK) - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPRenoRecovery (recuperação iniciada sem SACK), TcpExtTCPSackRecovery (recuperação iniciada com SACK), TcpExtTCPSACKDiscard (número de blocos SACK inválidos) - [Display Filter Reference: Transmission Control Protocol](https://www.wireshark.org/docs/dfref/t/tcp.html) · Wireshark · Filtro de exibição tcp.options.sack_perm (opção de SACK permitido no SYN) #### rt-zero-window · Janela zero (paralisação que parece retransmissão) · Zero window, often mistaken for retransmission Quando o programa que recebe não lê o socket a tempo e o buffer enche, quem envia para de transmitir e manda só zero window probes. A causa não está na rede. - Por quê → Efeito → Na tela: O cliente parado em um frame ou uma thread do servidor bloqueada deixa de ler o socket → A janela de recepção chega a 0, e quem envia para de transmitir e manda só probes (em intervalos cada vez maiores) → Travamento e depois avanço rápido. A captura de pacotes mostra “ZeroWindow” e não há perda - Sintomas: Travamento, Avanço rápido / Fatores: Paralisação - Quem: Só eu, Servidor inteiro / Quando: Quando junta muita gente, Aleatoriamente, de vez em quando - Responsável principal: Desenvolvimento do cliente (Equipe de desenvolvimento) / Também envolvidos: Desenvolvimento do servidor (Equipe de desenvolvimento), Infraestrutura de servidores (Equipe de infraestrutura) - O que fazer (Equipe de desenvolvimento): Verificar primeiro o lado que enviou o ZeroWindow na captura de pacotes (o lado que não consegue ler o socket), ler a rede sem parar em uma thread separada, dar ao buffer de recepção um tamanho adequado. Cliente: resolver as causas de frames parados, como carregamento e GC. Servidor: resolver o que bloqueia a thread que lê o socket. - O que fazer (Equipe de infraestrutura): Incluir no monitoramento o TcpExtTCPToZeroWindowAdv do nstat do servidor (vezes em que o servidor anunciou janela de recepção 0; se aumentar, o problema está no servidor e vai para o desenvolvimento do servidor), fornecer capturas de pacotes do lado do servidor. - No gráfico: Lacuna e depois tudo junto (Volume recebido por conexão, ocorrências de janela zero) - Onde olhar: Na captura de pacotes, achar o lado que anunciou janela 0 com o filtro do Wireshark tcp.analysis.zero_window. No nstat do servidor, separar TcpExtTCPToZeroWindowAdv (o servidor anunciou janela 0) de TcpExtTCPWinProbe (probes enviados para a janela 0 do outro lado) e ver o Recv-Q dos sockets do servidor (bytes que o programa ainda não leu, no ss) - Confirma se: Durante a parada não há retransmissões, só janela zero e probes. Se o TcpExtTCPToZeroWindowAdv do servidor ou o Recv-Q dos sockets do servidor aumentam, é o servidor que não lê a tempo; se o TcpExtTCPWinProbe aumenta, é o cliente que não lê a tempo - Descarta se: Sem janela zero na captura e com os mesmos dados sendo reenviados: a causa é perda ou retransmissão espúria - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Casos reais: roblox-2021 - Fontes: - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · Com a janela de recepção em 0, quem envia manda zero window probes e aumenta exponencialmente o intervalo entre eles - [7.5. TCP Analysis](https://www.wireshark.org/docs/wsug_html_chunked/ChAdvTCPAnalysis.html) · Wireshark · TCP ZeroWindow: pacote em que quem recebe anuncia janela 0 e faz quem envia parar de transmitir - [Display Filter Reference: Transmission Control Protocol](https://www.wireshark.org/docs/dfref/t/tcp.html) · Wireshark · Filtros de exibição tcp.analysis.zero_window e tcp.analysis.zero_window_probe - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpExtTCPToZeroWindowAdv: vezes em que a janela de recepção anunciada passou de um valor diferente de 0 para 0 - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nomes dos contadores no nstat: TCPToZeroWindowAdv, TCPWinProbe - [net/ipv4/tcp_output.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_output.c?h=v6.12) · Linux kernel · TCPWinProbe: aumenta a cada probe (tcp_send_probe0) enviado quando a janela de recepção do outro lado está em 0 - [net/ipv4/tcp_diag.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Em uma conexão, o Recv-Q do ss é o número de bytes recebidos que o programa ainda não leu #### rt-syn · Retransmissão do pedido de conexão (SYN) · SYN retransmission on connect Se o pedido de conexão se perde por estouro da fila de conexões (backlog) ou bloqueio no firewall, o SO do cliente volta a enviá-lo a partir de 1 segundo depois, com intervalos crescentes. - Por quê → Efeito → Na tela: O pico de conexões logo após a manutenção estoura a fila de conexões do servidor, ou o firewall ou a proteção contra DDoS descarta o SYN → O SO do cliente retransmite o SYN a partir de 1 segundo depois, em intervalos definidos (no Linux antigo, 1 s → 2 s → 4 s) → Depois de clicar em conectar, o atraso é de segundos exatos, como 1 s ou 3 s; se continuar falhando, não conecta ou fica em loading infinito - Sintomas: Não conecta / loading infinito / Fatores: Perda de pacotes - Quem: Servidor inteiro, Região ou operadora específica / Quando: Logo após login ou manutenção - Responsável principal: Desenvolvimento do servidor (Equipe de desenvolvimento) / Também envolvidos: Infraestrutura de servidores (Equipe de infraestrutura), Infraestrutura de rede (Equipe de infraestrutura), Desenvolvimento do cliente (Equipe de desenvolvimento) - O que fazer (Equipe de desenvolvimento): Servidor: aumentar o argumento backlog do listen (junto com o somaxconn), garantir que o servidor do jogo chame accept a tempo, sistema de fila de login. Cliente: aumentar o intervalo entre tentativas de conexão (espalhando-as aleatoriamente). - O que fazer (Equipe de infraestrutura): Servidores/SO: confirmar o estouro da fila de conexões do servidor pelo TcpExtListenOverflows e TcpExtListenDrops do nstat e pelo aviso “Possible SYN flooding” no log, aumentar o somaxconn (junto com o argumento do listen), SYN cookies. Rede: afrouxar o limite de SYN do firewall e da proteção contra DDoS. - Números de referência: No Linux (inclusive no Android), a primeira retransmissão do SYN sai após 1 segundo. Kernels antigos dobram o intervalo a partir daí e reenviam aos 1, 3, 7, 15 segundos …; a partir do 6.5, o kernel reenvia cinco vezes, em 1, 2, 3, 4 e 5 segundos, e depois passa a dobrar (7, 11, 19 segundos …) (tcp_syn_linear_timeouts=4). Celulares Android muitas vezes continuam com o kernel de lançamento mesmo após atualizar o SO, então o comportamento pode variar de aparelho para aparelho, mesmo na mesma versão do Android. Em qualquer caso, se todas as tentativas falham, a conexão desiste depois de cerca de 2 minutos. No Windows, conforme a versão e a configuração, o intervalo começa em 1 ou 3 segundos e cresce, e são 2–4 reenvios, então a desistência vem em 20–30 segundos (o valor daquele PC aparece em Max SYN Retransmissions no netsh int tcp show global). - No gráfico: Pico logo após abrir ou manutenção (Tentativas de conexão, estouros da fila de conexões) - Onde olhar: Ver TcpExtListenOverflows e TcpExtListenDrops no nstat do servidor e o aviso “Possible SYN flooding on port” no dmesg, e ver com ss -lnt se o Recv-Q do socket em escuta (conexões esperando accept) encosta no Send-Q (limite do backlog). Com captura no servidor, verificar se o SYN chega e se o SYN-ACK volta - Confirma se: No pico de conexões logo após a manutenção, TcpExtListenOverflows aumenta e o Recv-Q fica colado no Send-Q. Na captura, o SYN do mesmo cliente volta em intervalos de segundos e o servidor não responde - Descarta se: O SYN não chega ao servidor e os contadores do servidor estão parados: o firewall ou a proteção contra DDoS na frente descartou; ver o limite de SYN e o log de descartes desse equipamento. O servidor enviou o SYN-ACK e mesmo assim a conexão demora: perda no sentido de volta - Como verificar: Ferramentas de infra (sem precisar do código do jogo) - Fontes: - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · Primeiro RTO TCP_TIMEOUT_INIT = 1 segundo (valor inicial da RFC 6298) - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · RTO inicial de 1 segundo, dobrando a cada retransmissão - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_syn_retries com padrão 6, tcp_syn_linear_timeouts com padrão 4 (RTO do SYN 1, 1, 1, 1, 1, 2, 4 …), última retransmissão em 67 segundos e desistência em 131 segundos, somaxconn com padrão 4096, tcp_syncookies com padrão 1 - [tcp: make the first N SYN RTO backoffs linear](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ccce324dabfe2143519daf50ed8b1ef1d0c542f7) · Linux kernel · Commit que torna constante o intervalo das primeiras retransmissões de SYN, a partir do Linux 6.5 (o padrão 4 segue o comportamento do macOS e do iOS) - [Android common kernels](https://source.android.com/docs/core/architecture/kernel/android-common) · Android (Google) · Os kernels comuns de 5.10 a 6.18 são suportados em paralelo, e kernels de plataformas anteriores (ex.: android14-6.1) podem ser usados no lançamento ou na atualização de novos aparelhos Android - [TcpMaxConnectRetransmissions](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc938209(v=technet.10)) · Microsoft · Padrão antigo do Windows: 2 retransmissões de SYN, com a primeira espera de 3 segundos e depois dobrando; após a última, espera mais o dobro e desiste (3+6+12=21 segundos) - [TCP/IP connectivity issues troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/tcp-ip-connectivity-issues-troubleshooting) · Microsoft · O número de retransmissões de SYN varia conforme o SO e aparece em Max SYN Retransmissions no netsh int tcp show global - [listen(2) — Linux manual page](https://man7.org/linux/man-pages/man2/listen.2.html) · Linux man-pages · O argumento backlog do listen é limitado pelo somaxconn (padrão 4096 a partir do Linux 5.4; antes, 128) - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · Quando a fila de accept enche, o SYN é descartado e TcpExtListenOverflows e TcpExtListenDrops aumentam juntos; TcpExtTCPSynRetrans - [net/ipv4/tcp_input.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_input.c?h=v6.12) · Linux kernel · Mensagem de log “Possible SYN flooding on port …” - [net/ipv4/tcp_diag.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_diag.c?h=v6.12) · Linux kernel · Em um socket em escuta, o Recv-Q do ss é o número de conexões esperando accept, e o Send-Q é o limite do backlog ## Fontes por capítulo ### #l-client-game - [Slow rendering](https://developer.android.com/topic/performance/vitals/render) · Android (Google) · Para rodar a 60 FPS, cada frame precisa ser desenhado em 16 ms; se atrasar, o frame é pulado e aparecem engasgos - [Interpolation and extrapolation (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/interpolation.html) · Unity · Interpolação, que desenha o caminho entre snapshots que chegam espaçados, e extrapolação, que continua na mesma direção e velocidade quando os dados atrasam, com o limite dela - [Introduction to prediction (Netcode for Entities 6.5)](https://docs.unity3d.com/Packages/com.unity.netcode@6.5/manual/intro-to-prediction.html) · Unity · Predição: o cliente move o personagem com os próprios comandos sem esperar o resultado do servidor e corrige se divergir do servidor - [Peeking into VALORANT's Netcode](https://technology.riotgames.com/news/peeking-valorants-netcode) · Riot Games · Suavizar com um buffer os dados que chegam irregulares deixa o movimento liso, mas aumenta a latência na mesma medida; quando o palpite erra, o personagem pula ou desliza - [Garbage collection modes](https://docs.unity3d.com/Manual/performance-incremental-garbage-collection.html) · Unity · “Pico de GC” na simulação: com o GC incremental desligado, a thread principal para enquanto o heap inteiro é verificado e estoura o limite de 16 ms do frame - [Scripting.GarbageCollector.CollectIncremental](https://docs.unity3d.com/ScriptReference/Scripting.GarbageCollector.CollectIncremental.html) · Unity · Fatia de tempo de 3 ms do GC incremental na simulação: padrão de incrementalTimeSliceNanoseconds, 3 ms - [Shader loading](https://docs.unity3d.com/Manual/shader-loading.html) · Unity · “Carregamento de nova área” na simulação: na primeira vez que uma variante de shader é usada, a execução pode parar enquanto o driver a prepara para a GPU - [Frame Pacing library](https://developer.android.com/games/sdk/frame-pacing) · Android (Google) · “Limite do V-Sync” na simulação: uma tela de 60 Hz mostra o frame anterior mais uma vez quando não há frame novo - [Set fixed timestep to optimize physics simulation frequency](https://docs.unity3d.com/Manual/physics-optimization-cpu-frequency.html) · Unity · “Recuperação com passo fixo” na simulação: quando o frame é mais longo que o intervalo do passo, vários passos rodam em um só frame e a carga aumenta - [Handling variation in time](https://docs.unity3d.com/Manual/time-handling-variations.html) · Unity · “Recuperação limitada” na simulação (até 5 vezes por frame): o Unity limita o tempo de jogo de um frame a no máximo 1/3 de segundo para evitar a espiral de recuperação, e o relógio do jogo atrasa pelo tempo excedente ### #l-client-os - [Multitasking](https://learn.microsoft.com/en-us/windows/win32/procthread/multitasking) · Microsoft · Multitarefa preemptiva: cada thread recebe uma fatia de tempo (cerca de 20 ms, varia conforme o SO e a CPU) e, quando ela acaba, a vez passa para a próxima thread - [Scheduling Priorities](https://learn.microsoft.com/en-us/windows/win32/procthread/scheduling-priorities) · Microsoft · Entre as threads prontas para rodar, as de maior prioridade recebem fatias de tempo em rodízio (round-robin) - [Priority Boosts](https://learn.microsoft.com/en-us/windows/win32/procthread/priority-boosts) · Microsoft · Eleva a prioridade do processo da janela em primeiro plano para no mínimo a dos processos em segundo plano - [socket(7) — Linux manual page](https://man7.org/linux/man-pages/man7/socket.7.html) · Linux man-pages · Cada socket tem um buffer de recepção (SO_RCVBUF), com tamanhos padrão e máximo definidos nas configurações do sistema - [Wi-Fi low-latency mode](https://source.android.com/docs/core/connect/wifi-low-latency) · Android (Google) · No modo Wi-Fi de baixa latência do Android 10 ou superior, o framework desliga explicitamente o doze do Wi-Fi (economia de energia) quando o app está em primeiro plano e a tela está ligada - [Cached apps freezer](https://source.android.com/docs/core/perf/cached-apps-freezer) · Android (Google) · No Android 14 ou superior, apps em estado de cache são congelados após 10 segundos e não podem usar a CPU - [Extending your app’s background execution time](https://developer.apple.com/documentation/uikit/extending-your-app-s-background-execution-time) · Apple · O iOS suspende o app alguns segundos depois de ele ir para segundo plano - [_WDF_TIMER_CONFIG (wdftimer.h)](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdftimer/ns-wdftimer-_wdf_timer_config) · Microsoft · “Timer de 15,6 ms” na simulação: intervalo padrão do tick do relógio do sistema no Windows, 15,6 ms - [timeBeginPeriod function (timeapi.h)](https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod) · Microsoft · Timer de 1 ms na simulação: um programa pode pedir uma resolução de timer maior com timeBeginPeriod - [Customize the Windows performance power slider](https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/customize-power-slider) · Microsoft · Modo de economia de energia na simulação: o modo de energia do Windows ajusta as configurações de energia e de CPU para aumentar a duração da bateria, sacrificando desempenho - [Thermal API](https://developer.android.com/games/optimize/adpf/thermal) · Android (Google) · “Celular esquentando” na simulação: o aparelho mantém o alto desempenho só por um tempo limitado e depois sofre throttling pelo calor ### #l-memory - [Designs, Lessons and Advice from Building Large Distributed Systems (LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Base da tabela “Números de latência”: cache L1 0,5 ns, L2 7 ns, memória principal 100 ns, ida e volta no mesmo data center 0,5 ms, seek de disco 10 ms (dados de 2009; os números de cache da tabela são estimativas um pouco diferentes) - [Solidigm™ D7-P5520 and D7-P5620 Product Brief](https://www.solidigm.com/products/data-center/product-briefs/d7-p5520-p5620-product-brief.html) · Solidigm · Latência no percentil 99,99 (four-nines latency) de SSDs NVMe para servidor, 130 µs: base para a tabela dizer que a leitura de SSD e a releitura do swap ficam por volta de 100 µs - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rto_min_us com padrão 200.000 µs: espera mínima de 200 ms para retransmissão TCP no Linux (linha de retransmissão TCP da tabela) - [What is NUMA?](https://docs.kernel.org/mm/numa.html) · Linux kernel · A memória do lado de outra CPU (remota) tem acesso mais lento e menos largura de banda que a local (linha de NUMA da tabela) - [JEP 439: Generational ZGC](https://openjdk.org/jeps/439) · OpenJDK · Pausas do G1 de alguns ms a alguns segundos, pausas do ZGC de 1 ms ou menos (no texto, GC do heap inteiro de centenas de ms a alguns segundos; na tabela, GC de heap grande de 1 segundo) - [Available Collectors](https://docs.oracle.com/en/java/javase/25/gctuning/available-collectors.html) · Oracle · O ZGC abre mão de um pouco de vazão para manter a pausa máxima abaixo de 1 ms, e a pausa não depende do tamanho do heap - [Garbage Collector Implementation](https://docs.oracle.com/en/java/javase/25/gctuning/garbage-collector-implementation.html) · Oracle · Coleta geracional: a coleta minor, só na geração young, é curta, e a coleta major, no heap inteiro, leva muito mais tempo (modo geracional da simulação de GC) - [The Z Garbage Collector](https://docs.oracle.com/en/java/javase/25/gctuning/z-garbage-collector1.html) · Oracle · O ZGC faz o trabalho caro de forma concorrente e não pausa mais que 1 ms, mas, se a recuperação de memória não der conta, a aplicação pode parar esperando o GC (modo concorrente da simulação de GC) - [A Guide to the Go Garbage Collector](https://go.dev/doc/gc-guide) · Go · A fase de marcação do GC usa 25% da CPU e o programa fica mais lento nesse período; com muita alocação, as goroutines atrasam porque precisam ajudar o GC, o chamado assist (modo concorrente da simulação de GC) - [Go 1.8 Release Notes](https://go.dev/doc/go1.8) · Go · Pausas do GC do Go normalmente abaixo de 100 µs - [Debug a memory leak in .NET](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/debug-memory-leak) · .NET · Mesmo com GC, há vazamento se objetos que não são mais necessários continuam referenciados - [Concepts overview](https://docs.kernel.org/admin-guide/mm/concepts.html) · Linux kernel · Quando falta memória, o kernel recupera o page cache e as páginas que podem ir para o swap; se não bastar, o OOM killer encerra um processo à força (simulação de vazamento de memória) ### #l-disk - [Exos X18 Data Sheet](https://www.seagate.com/www-content/datasheets/pdfs/exos-x18-mango-DS2045-1N-2007US-en_US.pdf) · Seagate · HDD de 7.200 rpm: 170 IOPS em leitura aleatória de 4K, latência rotacional média de 4,16 ms (no texto, pouco mais de 150 operações por segundo no HDD; HDD da simulação de disco) - [D3-S4520 SSD](https://www.solidigm.com/products/data-center/d3/s4520.html) · Solidigm · SSD SATA: até 92K/48K IOPS em leitura/escrita aleatória de 4 KB (no texto, dezenas de milhares de operações no SSD) - [Solidigm™ D7-P5520 and D7-P5620 Product Brief](https://www.solidigm.com/products/data-center/product-briefs/d7-p5520-p5620-product-brief.html) · Solidigm · SSD NVMe: 1.000K/200K IOPS em leitura/escrita aleatória (no texto, centenas de milhares de operações) - [Amazon EBS General Purpose SSD volumes](https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html) · AWS · gp3 com 3.000 IOPS de base; o gp2 faz burst até 3.000 IOPS com créditos de I/O e volta ao desempenho de base quando os créditos acabam - [Amazon EBS-optimized instance types](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-optimized.html) · AWS · Instâncias pequenas só entregam o desempenho máximo do EBS por 30 minutos uma vez a cada 24 horas e depois voltam ao desempenho de base (ex.: t4g.2xlarge, base de 4.000 e máximo de 15.700 IOPS; premissa de nuvem com burst da simulação de disco) - [Managed disk bursting](https://learn.microsoft.com/en-us/azure/virtual-machines/disk-bursting) · Microsoft Azure · Discos e VMs pequenos fazem burst com créditos por até 30 minutos - [Concepts overview](https://docs.kernel.org/admin-guide/mm/concepts.html) · Linux kernel · Os dados escritos em arquivo vão primeiro para o page cache, são marcados como dirty e só depois são gravados no disco - [Documentation for /proc/sys/vm/](https://docs.kernel.org/admin-guide/sysctl/vm.html) · Linux kernel · Quando as escritas pendentes chegam ao dirty_ratio, o próprio processo que escreve passa a gravar no disco (limite de escrita do SO na simulação de disco) - [fsync(2) — Linux manual page](https://man7.org/linux/man-pages/man2/fsync.2.html) · Linux man-pages · fsync bloqueia até o dispositivo confirmar que a gravação terminou ### #l-db - [How MySQL Uses Indexes](https://dev.mysql.com/doc/refman/8.4/en/mysql-indexes.html) · MySQL · Sem índice, a tabela inteira é lida a partir da primeira linha (full scan) - [InnoDB Locking](https://dev.mysql.com/doc/refman/8.4/en/innodb-locking.html) · MySQL · Requisições para alterar a mesma linha esperam até terminar a transação que segura o lock da linha (hot row) - [Number Of Database Connections](https://wiki.postgresql.org/wiki/Number_Of_Database_Connections) · PostgreSQL · Depois que os recursos do BD se esgotam, aumentar as conexões derruba a vazão (base para, na simulação de BD, todos ficarem lentos mesmo com o pool maior quando faltam núcleos de CPU) - [WAL Configuration (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/wal-configuration.html) · PostgreSQL · O checkpoint é uma operação cara que grava de uma vez as páginas sujas, por padrão a cada 5 minutos ou a cada 1 GB de WAL; espalhar as escritas evita picos de I/O - [Semisynchronous Replication](https://dev.mysql.com/doc/refman/8.4/en/replication-semisync.html) · MySQL · Na replicação assíncrona, se o BD primário cai, transações já confirmadas podem não estar no BD reserva (rollback após o failover) - [Log-Shipping Standby Servers (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/warm-standby.html) · PostgreSQL · A replicação por streaming é assíncrona por padrão, então há atraso entre o commit e a aplicação na réplica (o que acabou de ser escrito não aparece na réplica) - [Asynchronous Commit (PostgreSQL Documentation)](https://www.postgresql.org/docs/current/wal-async-commit.html) · PostgreSQL · Acumular as gravações e descarregá-las mais tarde ganha velocidade em troca de perder as alterações recentes em caso de falha (a mesma estrutura de um servidor de jogo que salva a cada alguns minutos) ### #judge - [Service Level Objectives (Site Reliability Engineering, ch. 4)](https://sre.google/sre-book/service-level-objectives/) · Google · Usar percentis (50º, 95º, 99º) no lugar da média para ver o formato e a cauda da distribuição de latência - [The Tail at Scale](https://research.google/pubs/the-tail-at-scale/) · Google · Atrasos longos e ocasionais (latência de cauda) passam a dominar a experiência do serviço como um todo à medida que a escala cresce - [RFC 3550: RTP, A Transport Protocol for Real-Time Applications](https://www.rfc-editor.org/rfc/rfc3550) · IETF · Definição e cálculo do jitter de chegada (interarrival jitter) - [RFC 1812: Requirements for IP Version 4 Routers](https://www.rfc-editor.org/rfc/rfc1812) · IETF · Roteadores devem poder limitar a taxa de mensagens de erro ICMP como Time Exceeded e também podem limitar o Echo Reply (cuidado ao interpretar mtr e ping) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · icmp_ratelimit e icmp_ratemask: o Linux limita por padrão respostas ICMP como Time Exceeded e Destination Unreachable - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · Campos rtt (tempo médio de ida e volta)/rttvar no ss -ti - [pidstat(1) — Linux manual page](https://man7.org/linux/man-pages/man1/pidstat.1.html) · sysstat · pidstat -t: uso de CPU por thread - [bcc tools: runqlat examples](https://raw.githubusercontent.com/iovisor/bcc/master/tools/runqlat_example.txt) · IO Visor · Medição da distribuição da latência da fila de execução (tempo em que a thread esperou pela CPU) - [RIPE Atlas documentation](https://atlas.ripe.net/docs/) · RIPE NCC · Ferramenta pública de monitoramento sintético que roda ping e traceroute a partir de pontos de medição no mundo todo - [GeoLite2 Free Geolocation Data](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data) · MaxMind · Banco de dados público que associa país e ASN a endereços IP - [View CloudWatch metrics for your instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) · AWS · Monitoramento básico a cada 5 minutos, detalhado a cada 1 minuto (o intervalo de agregação esconde picos curtos) ### #l-nic - [NAPI](https://docs.kernel.org/networking/napi.html) · Linux kernel · Quando o dispositivo avisa de um pacote novo com uma interrupção, o kernel o retira e processa com NAPI; o agrupamento de interrupções (coalescência) normalmente é feito pelo dispositivo - [Scaling in the Linux Networking Stack](https://docs.kernel.org/networking/scaling.html) · Linux kernel · Arquitetura que distribui várias filas de recepção entre vários núcleos com RSS, com uma interrupção por fila e escolha da fila por hash - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · Pacotes descartados pelo dispositivo por falta de buffer (rx_missed_errors) e estatísticas por driver no ethtool -S - [ethtool(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ethtool.8.html) · ethtool · Configuração e consulta do ring buffer (-G), da coalescência de interrupções (-C), do hash de recepção (-N) e das estatísticas (-S) - [How to receive a million packets per second](https://blog.cloudflare.com/how-to-receive-a-million-packets/) · Cloudflare · Medição em que uma fila com um núcleo satura em cerca de 350 mil a 430 mil pacotes por segundo, e é preciso mais filas e núcleos para receber 1 milhão de pps (a simulação supõe uma vazão por núcleo mais folgada, de 700 mil pps) - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · Ao passar dos limites de largura de banda, PPS e rastreamento de conexões da instância na nuvem, os pacotes são enfileirados fora da instância e descartados; contadores de excesso de limite ### #l-server-os - [listen(2) — Linux manual page](https://man7.org/linux/man-pages/man2/listen.2.html) · Linux man-pages · Fila de conexões (backlog) e o teto do somaxconn (padrão 4.096 a partir do 5.4; antes, 128) - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · No Linux, quando a fila de accept enche, os pedidos de conexão (SYN) são descartados e TcpExtListenOverflows aumenta - [listen function (winsock2.h)](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen) · Microsoft · No Windows, com a fila cheia, o cliente recebe WSAECONNREFUSED - [getrlimit(2) — Linux manual page](https://man7.org/linux/man-pages/man2/getrlimit.2.html) · Linux man-pages · RLIMIT_NOFILE: limite de fds que um processo pode abrir; acima dele, EMFILE - [systemd-system.conf(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd-system.conf.5.html) · systemd · Padrão do limite de fds de um serviço, 1024:524288 (o erro de configuração de fd 1.024 na simulação) - [The /proc Filesystem](https://docs.kernel.org/filesystems/proc.html) · Linux kernel · O OOM killer escolhe o processo a encerrar por uma pontuação (badness) baseada na proporção de memória usada, ajustável com oom_score_adj - [Control Group v2](https://docs.kernel.org/admin-guide/cgroup-v2.html) · Linux kernel · Ao atingir memory.max sem conseguir reduzir o uso, o OOM killer roda dentro daquele cgroup; cpu.max limita a CPU - [proc_stat(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc_stat.5.html) · Linux man-pages · steal: tempo de CPU tomado por outros sistemas operacionais em ambiente virtualizado - [Exponential Backoff And Jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/) · AWS · Só com backoff exponencial, as tentativas ainda se concentram; misturar aleatoriedade (jitter) reduz a disputa (forma de retry da simulação) ### #l-socket - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · TCP como fluxo de bytes confiável e ordenado, definição de Nagle e de ACK atrasado - [RFC 768: User Datagram Protocol](https://www.rfc-editor.org/rfc/rfc768) · IETF · O UDP não garante entrega nem evita duplicação - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · Apps UDP que precisam de confiabilidade e ordem têm de implementá-las por conta própria - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · Opções de socket TCP como TCP_NODELAY, TCP_USER_TIMEOUT e keepalive - [socket(7) — Linux manual page](https://man7.org/linux/man-pages/man7/socket.7.html) · Linux man-pages · Opções de socket SO_SNDBUF, SO_RCVBUF, SO_KEEPALIVE e SO_LINGER - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Retransmissão rápida com 3 ACKs duplicados; depois de uma retransmissão por timer, a janela de congestionamento cai para 1 segmento (regra clássica dos livros usada na simulação) - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · RACK, que detecta perdas pelo horário de envio, sem contar ACKs duplicados - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · Recomendação de RTO mínimo de 1 segundo, com backoff que dobra a cada expiração - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rto_min_us com padrão de 200 ms no Linux, detecção de perda por RACK (tcp_recovery) - [include/net/tcp.h (Linux v6.12)](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · ACK atrasado de 40 ms do Linux na simulação: TCP_DELACK_MIN (HZ/25 = 40 ms), máximo TCP_DELACK_MAX (HZ/5 = 200 ms) - [Design issues - Sending small data segments over TCP with Winsock](https://learn.microsoft.com/en-us/previous-versions/troubleshoot/windows/win32/data-segment-tcp-winsock) · Microsoft · ACK atrasado de 200 ms do Windows na simulação: ao receber dados, arma um timer de ACK atrasado de 200 ms, e, combinado com o Nagle, faz pacotes pequenos esperarem pelo ACK - [RFC 896: Congestion Control in IP/TCP Internetworks](https://www.rfc-editor.org/rfc/rfc896) · IETF · Objetivo original da regra de Nagle: o problema dos terminais remotos, em que cada tecla de 1 byte gerava um pacote de 41 bytes - [send(2) — Linux manual page](https://man7.org/linux/man-pages/man2/send.2.html) · Linux man-pages · Com o buffer de envio cheio, um send() bloqueante não retorna ### #journey - [ITU-T G.114: One-way transmission time](https://www.itu.int/rec/T-REC-G.114-200305-I/en) · ITU · Atraso de propagação na fibra óptica de 5 µs/km (5 ms em 1.000 km, só ida); até 150 ms só de ida é quase imperceptível para a maioria das aplicações, mas tarefas muito interativas sentem o efeito mesmo abaixo de 100 ms - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Escala do trecho de internet por local de servidor na simulação: a partir de Seul, região de Busan 8 ms, Tóquio 30 ms, Singapura 68 ms, costa oeste dos EUA 124–136 ms, Europa 234–244 ms (mediana de ida e volta) - [The Internet at the Speed of Light (HotNets 2014)](https://conferences.sigcomm.org/hotnets/2014/papers/hotnets-XIII-final111.pdf) · ACM · Fator de rota de 1,5 na simulação: a rota real pelos roteadores é, em mediana, cerca de 1,5 vez a linha reta em fibra óptica - [Report ITU-R M.2134: Requirements related to technical performance for IMT-Advanced radio interface(s)](https://www.itu.int/pub/R-REP-M.2134-2008) · ITU · Requisito de latência em um sentido do trecho sem fio do LTE-Advanced abaixo de 10 ms (sem carga e com pacotes pequenos; o valor de LTE da simulação soma a isso carga e espera de escalonamento) - [Report ITU-R M.2410: Minimum requirements related to technical performance for IMT-2020 radio interface(s)](https://www.itu.int/pub/R-REP-M.2410-2017) · ITU · Requisito de latência em um sentido do trecho sem fio do 5G (IMT-2020) de 4 ms (eMBB, sem carga) - [An Experimental Study of Home Gateway Characteristics (IMC 2010)](https://conferences.sigcomm.org/imc/2010/papers/p260.pdf) · ACM · Fila do roteador na simulação: em roteadores domésticos, quando upload e download coincidem, a espera na fila pode chegar a centenas de ms (até cerca de 400 ms) - [Maximum transmission unit and maximum segment size](https://developers.cloudflare.com/magic-transit/reference/mtu-mss/) · Cloudflare · “Via proteção contra DDoS” na simulação: só o tráfego de entrada passa pela rede de proteção, e as respostas do servidor saem direto pela internet (DSR) ### #l-home - [RFC 7567: IETF Recommendations Regarding Active Queue Management](https://www.rfc-editor.org/rfc/rfc7567) · IETF · O acúmulo nas filas dos equipamentos é uma das principais causas de latência na internet, e a recomendação é usar gerenciamento de fila (AQM) por padrão - [RFC 8289: Controlled Delay Active Queue Management](https://www.rfc-editor.org/rfc/rfc8289) · IETF · Tempo de espera alvo do CoDel de 5 ms e intervalo de observação de 100 ms (fila SQM de cerca de 5 ms na simulação) - [RFC 8290: The Flow Queue CoDel Packet Scheduler and Active Queue Management Algorithm](https://www.rfc-editor.org/rfc/rfc8290) · IETF · FQ-CoDel: separa uma fila para cada fluxo por endereço e porta e despacha primeiro os fluxos pequenos, que não formam fila - [What Can I Do About Bufferbloat?](https://www.bufferbloat.net/projects/bloat/wiki/What_can_I_do_about_Bufferbloat/) · Bufferbloat.net · Usar um roteador com suporte a SQM, como cake ou fq_codel, e ajustar a velocidade do SQM medindo a latência sob carga - [An Experimental Study of Home Gateway Characteristics (IMC 2010)](https://conferences.sigcomm.org/imc/2010/papers/p260.pdf) · ACM · Medição de 34 roteadores domésticos: espera na fila de até cerca de 400 ms quando upload e download coincidem, retenção mediana do mapeamento UDP de 90 segundos - [Ending the Anomaly: Achieving Low Latency and Airtime Fairness in WiFi (USENIX ATC 2017)](https://www.usenix.org/system/files/conference/atc17/atc17-hoiland-jorgensen.pdf) · USENIX · Também na fila do rádio Wi-Fi há latência de centenas de ms sob carga, e um aparelho lento consome até o tempo de transmissão dos outros - [RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP](https://www.rfc-editor.org/rfc/rfc4787) · IETF · Requisito do timer de mapeamento UDP no NAT (pelo menos 2 minutos, com padrão recomendado de 5 minutos ou mais) e renovação por pacotes que saem de dentro - [RFC 8325: Mapping Diffserv to IEEE 802.11](https://www.rfc-editor.org/rfc/rfc8325) · IETF · O Wi-Fi usa CSMA/CA: com o canal ocupado, adia e transmite após um backoff aleatório - [Resolve Wi-Fi and Bluetooth issues caused by wireless interference](https://support.apple.com/en-us/102319) · Apple · Interferência de micro-ondas na simulação: micro-ondas, Bluetooth e outros atrapalham o Wi-Fi de 2,4 GHz, e mudar para 5 GHz melhora - [RFC 9438: CUBIC for Fast and Long-Distance Networks](https://www.rfc-editor.org/rfc/rfc9438) · IETF · Controle da taxa de upload na simulação: o CUBIC, ao sofrer perda, reduz a janela de envio a 0,7 vez (cerca de 30% a menos) e depois volta a aumentar ### #l-isp - [ITU-T G.114: One-way transmission time](https://www.itu.int/rec/T-REC-G.114-200305-I/en) · ITU · Atraso de propagação na fibra óptica de 5 µs/km: a luz percorre cerca de 200 mil km por segundo na fibra, e 1.000 km ida e volta levam no mínimo 10 ms - [The Internet at the Speed of Light (HotNets 2014)](https://conferences.sigcomm.org/hotnets/2014/papers/hotnets-XIII-final111.pdf) · ACM · A rota real pelos roteadores é, em mediana, cerca de 1,5 vez a linha reta em fibra óptica, e o ping mínimo é 3,2 vezes o da velocidade da luz (cerca de 2 vezes o da linha reta em fibra) - [Azure network round-trip latency statistics](https://learn.microsoft.com/en-us/azure/networking/azure-network-latency) · Microsoft Azure · Medianas reais de ida e volta a partir de Seul: Tóquio 30 ms, costa oeste dos EUA 124–136 ms, Europa 234–244 ms (Coreia–Europa dá cerca de 2,8 vezes a linha reta em fibra) - [AAE-1 & SMW5 cable cuts impact millions of users across multiple countries](https://blog.cloudflare.com/aae-1-smw5-cable-cuts/) · Cloudflare · O tráfego Europa–Ásia em geral passa pelo Egito, e o reparo de cabos submarinos leva de alguns dias a algumas semanas - [Quantifying the Causes of Path Inflation (SIGCOMM 2003)](https://conferences.sigcomm.org/sigcomm/2003/papers/p113-spring.pdf) · ACM · Políticas de peering entre operadoras e o roteamento entre domínios alongam muito as rotas - [Inferring Persistent Interdomain Congestion (SIGCOMM 2018)](https://www.caida.org/catalog/papers/2018_inferring_persistent_interdomain_congestion/inferring_persistent_interdomain_congestion.pdf) · ACM · Alguns pontos de interconexão entre operadoras mostram congestionamento recorrente, com latência e perda subindo todo dia no horário de pico - [RFC 4271: A Border Gateway Protocol 4 (BGP-4)](https://www.rfc-editor.org/rfc/rfc4271) · IETF · BGP, que troca as informações de rotas da internet, com hold time padrão recomendado de 90 segundos - [BGP updates in 2024](https://blog.apnic.net/2025/01/07/bgp-updates-in-2024/) · APNIC · Média diária do tempo até o roteamento se estabilizar de novo após uma mudança de rota: 25–35 segundos no IPv4 e 40–50 segundos no IPv6 - [Delayed Internet Routing Convergence (SIGCOMM 2000)](https://conferences.sigcomm.org/sigcomm/2000/conf/paper/sigcomm2000-5-2.pdf) · ACM · Depois de uma falha de rota, a convergência leva até vários minutos, com mais perda e latência nesse intervalo (medição feita em 2000) ### #l-dc-net - [High-Resolution Measurement of Data Center Microbursts (IMC 2017)](https://conferences.sigcomm.org/imc/2017/papers/imc17-final60.pdf) · ACM · A latência fim a fim na rede do data center fica abaixo de 1 ms, e mais de 70% dos bursts terminam em dezenas de µs, invisíveis na utilização média - [Data Center TCP (DCTCP) (SIGCOMM 2010)](https://conferences.sigcomm.org/sigcomm/2010/papers/sigcomm/p63.pdf) · ACM · Switches comuns dividem buffers rasos entre várias portas, e, quando vários fluxos convergem para uma porta por um instante, o buffer estoura e há perda - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · Padrões do número máximo de entradas e do tempo de retenção da tabela de rastreamento de conexões (UDP 30 segundos, stream 120 segundos, TCP estabelecido 5 dias) - [Edit attributes for your Application Load Balancer](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/edit-load-balancer-attributes.html) · AWS · Timeout de inatividade do ALB com padrão de 60 segundos; ao vencer, o load balancer fecha a conexão - [Network Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/network-load-balancers.html) · AWS · Padrões de load balancer na simulação: NLB TCP 350 segundos, UDP 120 segundos (não alterável), e, após a inatividade, o rastreamento para silenciosamente - [Configure load balancer TCP reset and idle timeout](https://learn.microsoft.com/en-us/azure/load-balancer/load-balancer-tcp-idle-timeout) · Microsoft Azure · Timeout de inatividade do Azure Load Balancer com padrão de 4 minutos - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Padrões de rastreamento de conexões do grupo de segurança, e explicação de que o timeout de inatividade TCP de load balancers e firewalls costuma ser de 60–90 minutos - [Flow-Based Sessions](https://www.juniper.net/documentation/us/en/software/junos/flow-packet-processing/topics/topic-map/security-flow-based-session-for-srx-series-devices.html) · Juniper Networks · Firewall de empresa na simulação: timeout de sessão padrão do firewall SRX, TCP 1.800 segundos (30 minutos) e UDP 60 segundos - [An Experimental Study of Home Gateway Characteristics (IMC 2010)](https://conferences.sigcomm.org/imc/2010/papers/p260.pdf) · ACM · TCP de 1 hora no roteador doméstico da simulação: mediana do mapeamento TCP de cerca de 60 minutos. O mapeamento UDP variou de 30 a 691 segundos conforme o aparelho, com mediana de 90 segundos em um sentido e cerca de 180 segundos nos dois sentidos - [A Multi-perspective Analysis of Carrier-Grade NAT Deployment (IMC 2016)](https://www.icir.org/vern/papers/cgn-imc16.pdf) · ACM · UDP de 30 segundos no CGNAT e de 1 minuto no roteador doméstico da simulação: mediana do mapeamento UDP do CGN de 35 segundos na rede fixa e 65 segundos na rede móvel, 74% dos NATs medidos com 1 minuto ou menos, e a maioria dos NATs de roteadores domésticos (CPE) com 65 segundos - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP keepalive na simulação: por padrão, após 2 horas (7.200 segundos) de inatividade, verifica 9 vezes em intervalos de 75 segundos e, sem resposta, encerra a conexão - [Cached apps freezer](https://source.android.com/docs/core/perf/cached-apps-freezer) · Android (Google) · Celular em segundo plano na simulação: no Android 14 ou superior, processos de apps em estado de cache são congelados após 10 segundos - [RFC 5880: Bidirectional Forwarding Detection (BFD)](https://www.rfc-editor.org/rfc/rfc5880) · IETF · BFD, que detecta falhas de rota mais rápido que os Hellos de segundos dos protocolos de roteamento - [RFC 2923: TCP Problems with Path MTU Discovery](https://www.rfc-editor.org/rfc/rfc2923) · IETF · Black hole de MTU do caminho: com o ICMP bloqueado, só os pacotes grandes somem ### #basics - [Teletraffic Engineering Handbook (ITU-D Study Group 2 Question 16/2)](https://www.itu.int/dms_pub/itu-d/opb/stg/D-STG-SG02.16.2.1-2002-PDF-E.pdf) · ITU · Espera média no M/M/1, W = A·s/(1−A): com utilização de 50%, 80% e 90%, 1, 4 e 9 vezes o tempo de processamento. Com a mesma utilização, quanto mais workers (servidores) e mais regulares as chegadas, menor a espera - [CloudWatch metrics that are available for your instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html) · AWS · O CPUUtilization do EC2 é o valor da instância inteira, agregado a cada 5 minutos por padrão e a cada 1 minuto no monitoramento detalhado - [Designs, Lessons and Advice from Building Large Distributed Systems (Jeff Dean, LADIS 2009 keynote)](https://www.cs.cornell.edu/projects/ladis2009/talks/dean-keynote-ladis2009.pdf) · Google · Acesso à memória principal 100 ns, ida e volta dentro do mesmo data center 500.000 ns (0,5 ms) - [ITU-T G.114: One-way transmission time](https://www.itu.int/rec/T-REC-G.114-200305-I/en) · ITU · Atraso de propagação na fibra óptica de 5 µs/km (base do cálculo do limite da velocidade da luz) - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Padrões do Half-Life: 20 atualizações por segundo e interpolação de 100 ms. Com 10 por segundo, uma interpolação de 200 ms aguenta a perda de uma atualização - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_rto_min_us com padrão 200000 (200 ms) - [Factors influencing the latency of simple reaction time (Frontiers in Human Neuroscience, 2015)](https://doi.org/10.3389/fnhum.2015.00131) · Frontiers · Tempo médio de reação simples de cerca de 231 ms (213 ms corrigindo a latência do equipamento) - [A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022)](https://web.cs.wpi.edu/~claypool/papers/lag-taxonomy/paper.pdf) · ACM · Mesmo latências abaixo de 100 ms afetam o desempenho em tarefas de jogo, e em ações como arrastar se percebe até cerca de 10 ms - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Jogadores experientes percebem diferenças de cerca de 10 ms em testes cegos - [Latency and Player Actions in Online Games (Communications of the ACM, 2006)](https://web.cs.wpi.edu/~claypool/papers/precision-deadline/final.pdf) · ACM · Tolerância de latência por gênero: primeira pessoa cerca de 100 ms, terceira pessoa (RPG, MMO) cerca de 500 ms, RTS cerca de 1.000 ms - [JEP 333: ZGC: A Scalable Low-Latency Garbage Collector](https://openjdk.org/jeps/333) · OpenJDK · O G1, com heap de 128 GB, teve pausas médias de 157 ms e máximas de 544 ms; o ZGC, cerca de 1–2 ms, independentemente do tamanho do heap e dos dados vivos - [CommonNetworkParametersExtensions (Unity Transport 2.5)](https://docs.unity3d.com/Packages/com.unity.transport@2.5/api/Unity.Networking.Transport.CommonNetworkParametersExtensions.html) · Unity · disconnectTimeoutMS: se nada for recebido durante esse tempo, a conexão é encerrada (padrão 30.000 ms) ### #lab - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · A interpolação desenha o passado, mas em troca fica lisa; a extrapolação não sabe das mudanças de direção e pula quando erra. O erro de predição é corrigido pelo resultado do servidor - [UDP vs. TCP](https://gafferongames.com/post/udp_vs_tcp/) · Gaffer On Games · Quando o TCP perde um pacote, não entrega dados novos que já chegaram até a retransmissão (normalmente 2×RTT ou mais) - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · Repetir em cada pacote os comandos ainda não confirmados evita esperar a retransmissão (no pior caso, 2 segundos de comandos) - [Snapshot Interpolation](https://gafferongames.com/post/snapshot_interpolation/) · Gaffer On Games · Desenhar assim que recebe gera engasgos por causa do jitter; o buffer de interpolação aumenta um pouco a latência e deixa o movimento liso - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · Quando o movimento do cliente se perde por problema de conexão ou chega errado, o servidor corrige a posição (rubber banding) - [Source SDK 2013: player.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player.cpp) · Valve · Um orçamento de comandos acumulado a cada tick limita os comandos que chegam em rajada. Rígido demais, causa engasgos até em jogadores normais - [Introducing Time Dilation (TiDi)](https://www.eveonline.com/news/view/introducing-time-dilation-tidi) · CCP Games · Design que, com o servidor sobrecarregado, desacelera o relógio do jogo (Time Dilation) para que tudo corra mais devagar - [CommonNetworkParametersExtensions (Unity Transport 2.5)](https://docs.unity3d.com/Packages/com.unity.transport@2.5/api/Unity.Networking.Transport.CommonNetworkParametersExtensions.html) · Unity · Timeout de inatividade que encerra a conexão quando nada é recebido por um certo tempo ### #symptoms - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Quando faltam atualizações, a entidade para na última posição (engasgos) ou é extrapolada e depois pula (teleporte). O tempo de extrapolação precisa de limite - [Understanding Networked Movement in the Character Movement Component for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/understanding-networked-movement-in-the-character-movement-component-for-unreal-engine) · Epic Games · Quando o movimento do cliente se perde ou difere do cálculo do servidor, o servidor envia uma correção e devolve a posição (rubber banding) - [UDP vs. TCP](https://gafferongames.com/post/udp_vs_tcp/) · Gaffer On Games · O TCP acumula os dados seguintes até receber a retransmissão do pacote perdido e então entrega tudo de uma vez (avanço rápido) - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · Quando comandos atrasados chegam todos juntos, vários frames são calculados de uma vez para recuperar o atraso - [Introducing Time Dilation (TiDi)](https://www.eveonline.com/news/view/introducing-time-dilation-tidi) · CCP Games · Time Dilation (TiDi), que desacelera o relógio do jogo quando o servidor está sobrecarregado, e o fenômeno das tarefas que atrasam vários segundos sob sobrecarga - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · O tempo de buffering depende do tick rate do servidor e do frame de renderização do cliente - [Using Gameplay Abilities in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-gameplay-abilities-in-unreal-engine) · Epic Games · O servidor pode reverter uma habilidade executada por predição (ação perdida / rollback) - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · Atores que o servidor considera irrelevantes não são replicados ou são removidos no cliente (invisível / entidade fantasma) - [CommonNetworkParametersExtensions (Unity Transport 2.5)](https://docs.unity3d.com/Packages/com.unity.transport@2.5/api/Unity.Networking.Transport.CommonNetworkParametersExtensions.html) · Unity · Passado o timeout de inatividade, a conexão é encerrada (desconexão) ### #sync - [Latency Compensating Methods in Client/Server In-game Protocol Design and Optimization (Yahn W. Bernier, GDC 2001)](https://web.cs.wpi.edu/~claypool/courses/4513-B03/papers/games/bernier.pdf) · Valve · Princípios de servidor autoritativo, predição e reconciliação no cliente, interpolação e compensação de lag, e compromissos como o “tiro atrás da esquina” - [What Every Programmer Needs To Know About Game Networking](https://gafferongames.com/post/what_every_programmer_needs_to_know_about_game_networking/) · Gaffer On Games · Evolução do netcode do lockstep P2P para cliente/servidor e para a predição no cliente - [Using Gameplay Abilities in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/using-gameplay-abilities-in-unreal-engine) · Epic Games · Compromisso entre responsividade e precisão de Local Predicted e Server Initiated - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Autoridade do servidor, predição, buffering, registro de acerto com volta no tempo e o limite da volta no tempo - [NetworkTime and ticks (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/advanced-topics/networktime-ticks.html) · Unity · Método de agendar eventos pelo horário do servidor para reproduzi-los - [1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond](https://www.gamedeveloper.com/programming/1500-archers-on-a-28-8-network-programming-in-age-of-empires-and-beyond) · Game Developer · Lockstep: comandos agendados para dois turnos depois, duração do turno ajustada ao computador mais lento; uma latência constante de 500 ms é aceitável, mas latência irregular incomoda - [Deterministic Lockstep](https://gafferongames.com/post/deterministic_lockstep/) · Gaffer On Games · No lockstep, o jogo só avança quando chegam todos os comandos; um buffer de atraso de reprodução absorve o jitter - [GGPO Rollback Networking SDK](https://www.ggpo.net/) · GGPO · Rollback: avança prevendo os comandos do adversário e, se errar, volta no tempo e recalcula - [8 Frames in 16ms: Rollback Networking in 'Mortal Kombat' and 'Injustice 2'](https://www.gdcvault.com/play/1025471/8-Frames-in-16ms-Rollback) · GDC · O rollback elimina o atraso de input local do lockstep, recalculando até 8 frames - [Latency and Player Actions in Online Games (Communications of the ACM, 2006)](https://web.cs.wpi.edu/~claypool/papers/precision-deadline/final.pdf) · ACM · A mesma latência afeta de forma diferente conforme a precisão e o prazo da ação e a perspectiva (primeira pessoa, terceira pessoa, onisciente) - [Networking Overview for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/networking-overview-for-unreal-engine) · Epic Games · Vantagens e carga do host em listen server - [Factors influencing the latency of simple reaction time (Frontiers in Human Neuroscience, 2015)](https://doi.org/10.3389/fnhum.2015.00131) · Frontiers · Tempo de reação simples humano de cerca de 0,23 segundo ### #partial - [Peeking into VALORANT's Netcode](https://www.riotgames.com/en/news/peeking-valorants-netcode) · Riot Games · Quando um jogador sai de sincronia, só ele recebe correção, e os outros nove veem tudo liso. O registro de acerto com volta no tempo tem limite - [State Synchronization](https://gafferongames.com/post/state_synchronization/) · Gaffer On Games · Os pacotes chegam agrupados, como 2 em um frame e 0 no seguinte, e o buffer de jitter os distribui de forma regular - [Source SDK 2013: player.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player.cpp) · Valve · Orçamento de comandos que distribui pelos ticks os comandos que chegam em rajada, e os efeitos colaterais de um limite rígido - [Source SDK 2013: player_lagcompensation.cpp](https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/master/src/game/server/player_lagcompensation.cpp) · Valve · Limite da volta no tempo na Source Engine, sv_maxunlag, com padrão de 1 segundo - [A Survey and Taxonomy of Latency Compensation Techniques for Network Computer Games (ACM Computing Surveys, 2022)](https://web.cs.wpi.edu/~claypool/papers/lag-taxonomy/paper.pdf) · ACM · O “tiro atrás da esquina” da compensação de lag, e o atraso de input para alinhar os comandos de todos - [send(2) — Linux manual page](https://man7.org/linux/man-pages/man2/send.2.html) · Linux man-pages · Com o buffer de envio cheio, send() espera no modo bloqueante e, no não bloqueante, retorna na hora com EAGAIN - [Networking Overview for Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/networking-overview-for-unreal-engine) · Epic Games · O host em listen server leva vantagem sobre os outros jogadores - [Authority (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/manual/terms-concepts/authority.html) · Unity · Autoridade distribuída: cada cliente calcula parte das entidades - [Actor Relevancy in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-relevancy-in-unreal-engine) · Epic Games · O servidor envia a cada conexão só os atores relevantes e os remove no cliente quando deixam de ser relevantes - [NetworkConfig class (Netcode for GameObjects 2.5)](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.5/api/Unity.Netcode.NetworkConfig.html) · Unity · Mensagens de entidades ainda não criadas ficam retidas e são descartadas depois de um tempo (SpawnTimeout) - [RFC 8085: UDP Usage Guidelines](https://www.rfc-editor.org/rfc/rfc8085) · IETF · Um pacote UDP fragmentado se perde inteiro se um único fragmento se perder - [Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE](https://learn.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse) · Microsoft · Quando dois sockets compartilham a mesma porta, não dá para saber qual deles vai receber o pacote - [RFC 6269: Issues with IP Address Sharing](https://www.rfc-editor.org/rfc/rfc6269) · IETF · Quando vários assinantes compartilham um endereço IP, não dá para distinguir usuários só pelo IP - [Application.runInBackground](https://docs.unity3d.com/ScriptReference/Application-runInBackground.html) · Unity · Comportamento padrão de suspender o app em segundo plano - [Actor Priority in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/actor-priority-in-unreal-engine) · Epic Games · Com a largura de banda saturada, só alguns atores são replicados, conforme a prioridade ### #retrans - [RFC 6298: Computing TCP's Retransmission Timer](https://www.rfc-editor.org/rfc/rfc6298) · IETF · RTO = SRTT + max(G, 4·RTTVAR), inicial de 1 segundo, recomendação de mínimo de 1 segundo, dobra a cada expiração, um eventual teto deve ser de pelo menos 60 segundos, pacotes retransmitidos ficam fora das amostras de RTT (Karn) - [RFC 5681: TCP Congestion Control](https://www.rfc-editor.org/rfc/rfc5681) · IETF · Retransmissão rápida no terceiro ACK duplicado; após o RTO, recomeça com janela de congestionamento de 1 segmento (janela de perda) - [RFC 6675: A Conservative Loss Recovery Algorithm Based on Selective Acknowledgment (SACK) for TCP](https://www.rfc-editor.org/rfc/rfc6675) · IETF · Recuperação de perdas que identifica os pacotes faltantes pelas informações do SACK (sinais de ACK duplicado e de SACK para a retransmissão rápida) - [RFC 8985: The RACK-TLP Loss Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc8985) · IETF · Folga de reordenação do RACK (min_RTT/4) e ajuste por DSACK, espera do TLP de 2·SRTT (com folga para ACK atrasado quando só há um pacote sem confirmação), rearme do RTO depois do envio do TLP, SACK obrigatório - [RFC 2018: TCP Selective Acknowledgment Options](https://www.rfc-editor.org/rfc/rfc2018) · IETF · SACK: quem recebe informa os trechos faltando - [RFC 2883: An Extension to the Selective Acknowledgement (SACK) Option for TCP](https://www.rfc-editor.org/rfc/rfc2883) · IETF · DSACK: avisa que recebeu de novo algo que já tinha recebido, revelando retransmissões espúrias - [RFC 5682: Forward RTO-Recovery (F-RTO): An Algorithm for Detecting Spurious Retransmission Timeouts with TCP](https://www.rfc-editor.org/rfc/rfc5682) · IETF · F-RTO: detecção de RTO espúrio - [RFC 3522: The Eifel Detection Algorithm for TCP](https://www.rfc-editor.org/rfc/rfc3522) · IETF · Com timestamps, descobre depois se a recuperação foi desnecessária (reversão da janela de congestionamento na simulação) - [RFC 7323: TCP Extensions for High Performance](https://www.rfc-editor.org/rfc/rfc7323) · IETF · Opções de timestamps e window scaling; sem scaling, a janela é de no máximo 64 KiB - [RFC 6937: Proportional Rate Reduction for TCP](https://www.rfc-editor.org/rfc/rfc6937) · IETF · PRR: durante a recuperação, reduz o volume enviado conforme o volume recém-entregue (limite de envio durante a recuperação na simulação) - [RFC 9438: CUBIC for Fast and Long-Distance Networks](https://www.rfc-editor.org/rfc/rfc9438) · IETF · O CUBIC reduz a janela de congestionamento a 0,7 vez na perda (redução de 30% na simulação) - [RFC 9293: Transmission Control Protocol (TCP)](https://www.rfc-editor.org/rfc/rfc9293) · IETF · Zero window probe: mesmo com a janela em 0, envia probes, com intervalo crescendo exponencialmente - [RFC 9000: QUIC: A UDP-Based Multiplexed and Secure Transport](https://www.rfc-editor.org/rfc/rfc9000) · IETF · No QUIC, uma perda bloqueia só o stream que estava naquele pacote, e os outros streams continuam (separação de fluxos) - [RFC 2475: An Architecture for Differentiated Services](https://www.rfc-editor.org/rfc/rfc2475) · IETF · Definição: o shaping atrasa os pacotes, e o policing descarta o excedente - [RFC 3168: The Addition of Explicit Congestion Notification (ECN) to IP](https://www.rfc-editor.org/rfc/rfc3168) · IETF · ECN: sinaliza o congestionamento sem descartar pacotes - [Smart Queue Management](https://www.bufferbloat.net/projects/cerowrt/wiki/Smart_Queue_Management/) · Bufferbloat.net · SQM no roteador: escalonamento por fluxo, AQM e shaping reduzem o estouro de fila e o bufferbloat - [RFC 1191: Path MTU discovery](https://www.rfc-editor.org/rfc/rfc1191) · IETF · Descoberta do MTU do caminho pelo ICMP de pacote grande demais (tipo 3, código 4) - [RFC 1812: Requirements for IP Version 4 Routers](https://www.rfc-editor.org/rfc/rfc1812) · IETF · Roteadores podem limitar a taxa de geração de mensagens de erro ICMP (resultados de mtr em que só um salto intermediário parece ter perda) - [RFC 2991: Multipath Issues in Unicast and Multicast Next-Hop Selection](https://www.rfc-editor.org/rfc/rfc2991) · IETF · Com vários caminhos, é difícil confiar em resultados de diagnóstico como ping e traceroute; método de fixar o caminho pelo hash do fluxo - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · tcp_recovery (padrão 0x1, RACK; a partir do 6.17, o RACK é a única detecção de perda e definir 0 não tem efeito), tcp_early_retrans (padrão 3; 0 desliga o TLP), tcp_sack, tcp_dsack e tcp_timestamps (ligados por padrão), tcp_thin_linear_timeouts (menos de 4 pacotes in flight, até 6 vezes de forma linear), tcp_rto_max_ms, tcp_mtu_probing e tcp_base_mss, tcp_rto_min_us, tcp_retries2 (padrão 15, cerca de 924,6 segundos), tcp_syn_linear_timeouts, tcp_notsent_lowat - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · TcpOutSegs não inclui retransmissões; significado de TCPLossProbes, TCPLossProbeRecovery, TCPLostRetransmit, TCPSpuriousRTOs, TCPDSACKRecv e TCPSynRetrans - [net/ipv4/proc.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/proc.c?h=v6.12) · Linux kernel · Nomes dos contadores no nstat (RetransSegs, TCPTimeouts, TCPLossProbes, TCPSpuriousRTOs, TCPDSACKRecv etc.) - [Thin-streams and TCP](https://docs.kernel.org/networking/tcp-thin.html) · Linux kernel · Em thin streams como os de jogos, a retransmissão rápida funciona mal e a conexão depende de timeouts longos; TCP_THIN_LINEAR_TIMEOUTS - [include/net/tcp.h](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/net/tcp.h?h=v6.12) · Linux kernel · TCP_RTO_MIN 200 ms, TCP_RTO_MAX 120 segundos, TCP_TIMEOUT_INIT 1 segundo, ACK atrasado de 40–200 ms (TCP_DELACK_MIN e MAX), TCP_BASE_MSS 1.024, critério de thin stream (menos de 4 pacotes in flight) - [net/ipv4/tcp_input.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_input.c?h=v6.12) · Linux kernel · RTO = SRTT + rttvar (pelo menos o RTO mínimo), RACK só em conexões com SACK, PRR para reduzir a janela de congestionamento durante a recuperação - [net/ipv4/tcp_output.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_output.c?h=v6.12) · Linux kernel · TLP só em conexões com SACK, espera de 2·RTT, somando o RTO mínimo quando só há um pacote sem confirmação - [net/ipv4/tcp_timer.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_timer.c?h=v6.12) · Linux kernel · Quando o RTO se repete tcp_retries1 vezes, detecção de black hole e sondagem de MTU; timeouts lineares para thin streams e SYN - [net/ipv4/tcp_recovery.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_recovery.c?h=v6.12) · Linux kernel · Folga do RACK = min(min_RTT/4 × etapa, SRTT); retransmissões confirmadas mais rápido que o RTT mínimo ficam fora da referência - [net/ipv4/tcp_ipv4.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_ipv4.c?h=v6.12) · Linux kernel · Inicialização dos padrões: tcp_early_retrans 3, tcp_recovery RACK, tcp_syn_linear_timeouts 4, tcp_base_mss 1.024 (tcp_mtu_probing não é definido e fica em 0) - [net/ipv4/tcp_bbr.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/tcp_bbr.c?h=v6.12) · Linux kernel · pacing_rate do BBR = pacing_gain × largura de banda do gargalo (envio regular com pacing) - [tcp: use RACK to detect losses](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4f41b1c58a32537542f14c1150099131613a5e8a) · Linux kernel · Introdução do RACK e do tcp_recovery (Linux 4.4), no início como auxiliar do método antigo - [tcp: disable RFC6675 loss detection](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b38a51fec1c1f693f03b1aa19d0622123634d4b7) · Linux kernel · O RACK passa a ser a detecção de perda padrão (2018, Linux 4.18) - [tcp: remove obsolete and unused RFC3517/RFC6675 loss recovery code](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1c120191dcec510cc17d587ece48a7ae875a90c5) · Linux kernel · Remoção do código de recuperação de perdas da RFC6675 (Linux 6.17), com a explicação de que o RACK-TLP é o padrão desde 2018 - [tcp: make the first N SYN RTO backoffs linear](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ccce324dabfe2143519daf50ed8b1ef1d0c542f7) · Linux kernel · As 4 primeiras etapas de backoff do RTO do SYN deixam de dobrar (depois do primeiro RTO de 1 s, mais quatro esperas de 1 s, e só então 2, 4 segundos …; Linux 6.5) - [tcp: add sysctl_tcp_rto_min_us](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f086edef71be7174a16c1ed67ac65a085cda28b1) · Linux kernel · RTO mínimo para o servidor inteiro, tcp_rto_min_us (Linux 6.11) - [tcp: add the ability to control max RTO](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=54a378f43425085d0684679d99735696b69165bc) · Linux kernel · Opção de socket TCP_RTO_MAX_MS, 1–120 segundos (Linux 6.15) - [tcp: support TCP_RTO_MIN_US for set/getsockopt use](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f38805c5d26fe4af97837c10d58074a7496638bf) · Linux kernel · Opção de socket TCP_RTO_MIN_US, que define o RTO mínimo por conexão (Linux 6.15) - [Android common kernels](https://source.android.com/docs/core/architecture/kernel/android-common) · Android (Google) · Os kernels comuns do Android com suporte são 5.10 ou superiores (mais novos que o 4.18, em que o RACK virou padrão) - [tcp(7) — Linux manual page](https://man7.org/linux/man-pages/man7/tcp.7.html) · Linux man-pages · TCP_NODELAY (desliga o Nagle), TCP_USER_TIMEOUT (só define quando desistir, sem mudar o momento das retransmissões), TCP_KEEPIDLE, TCP_INFO - [ip-route(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ip-route.8.html) · iproute2 · Opção rto_min por rota - [tc-fq(8) — Linux manual page](https://man7.org/linux/man-pages/man8/tc-fq.8.html) · iproute2 · Pacing por conexão da fila fq e SO_MAX_PACING_RATE - [iptables-extensions(8) — Linux manual page](https://man7.org/linux/man-pages/man8/iptables-extensions.8.html) · netfilter · TCPMSS --clamp-mss-to-pmtu: contorna trechos com ICMP bloqueado ajustando o MSS no SYN - [ss(8) — Linux manual page](https://man7.org/linux/man-pages/man8/ss.8.html) · iproute2 · rto (ms), backoff (número de backoffs exponenciais), rtt/rttvar e cwnd no ss -i - [misc/ss.c](https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/misc/ss.c?h=v6.12.0) · iproute2 · Saídas retrans:atual/acumulado, lost, reordering, bytes_sent e bytes_retrans do ss -ti - [nstat(8) — Linux manual page](https://man7.org/linux/man-pages/man8/nstat.8.html) · iproute2 · Por padrão, o nstat mostra o incremento desde a execução anterior - [Demonstrations of tcpretrans, the Linux eBPF/bcc version](https://raw.githubusercontent.com/iovisor/bcc/master/tools/tcpretrans_example.txt) · IO Visor · Uma linha por retransmissão com endereço, porta e estado; -c soma por fluxo, -l inclui as tentativas de TLP - [Interface statistics](https://docs.kernel.org/networking/statistics.html) · Linux kernel · ip -s -s link mostra até os erros detalhados; significado de rx_missed_errors e rx_crc_errors; estatísticas por driver no ethtool -S - [drivers/net/ethernet/intel/igb/igb_ethtool.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/intel/igb/igb_ethtool.c?h=v6.12) · Linux kernel · Exemplos de nomes de contadores por driver: rx_missed_errors, rx_no_buffer_count, rx_crc_errors - [Ethtool counters](https://docs.kernel.org/networking/device_drivers/ethernet/mellanox/mlx5/counters.html) · Linux kernel · rx_out_of_buffer e rx_discards_phy do mlx5 - [net/core/net-procfs.c](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/core/net-procfs.c?h=v6.12) · Linux kernel · /proc/net/softnet_stat tem uma linha por CPU, em hexadecimal, 2ª coluna dropped, 3ª coluna time_squeeze - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · Significado de bw_in, bw_out, pps, conntrack e linklocal_allowance_exceeded; para ver no CloudWatch, é preciso instalar o agente do CloudWatch - [High-Resolution Measurement of Data Center Microbursts](https://research.facebook.com/publications/high-resolution-measurement-of-data-center-microbursts/) · Meta · A maioria dos bursts termina em dezenas de µs, então a utilização média por minuto não revela a causa dos descartes (IMC 2017) - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · -T (--tcp) para TCP SYN, -P (--port) para a porta de destino - [pathping](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/pathping) · Microsoft · Comando de diagnóstico de rota do Windows que envia várias vezes e calcula a perda e a latência por salto - [Display Filter Reference: Transmission Control Protocol](https://www.wireshark.org/docs/dfref/t/tcp.html) · Wireshark · Filtros de exibição tcp.analysis.retransmission, fast_retransmission, spurious_retransmission, duplicate_ack, lost_segment e zero_window - [7.5. TCP Analysis](https://www.wireshark.org/docs/wsug_html_chunked/ChAdvTCPAnalysis.html) · Wireshark · Critérios para classificar retransmissão, retransmissão rápida, retransmissão espúria e ZeroWindow - [Network-Related Performance Counters](https://learn.microsoft.com/en-us/windows-server/networking/technologies/network-subsystem/net-sub-performance-counters) · Microsoft · TCPv4 Segments Retransmitted/sec·Segments Sent/sec, Network Interface Packets Received Discarded - [TCP/IP connectivity issues troubleshooting](https://learn.microsoft.com/en-us/troubleshoot/windows-client/networking/tcp-ip-connectivity-issues-troubleshooting) · Microsoft · Consulta das configurações globais do TCP (Max SYN Retransmissions) com netsh int tcp show global, captura simultânea nas duas pontas para confirmar perda no meio do caminho - [Packet Monitor (Pktmon)](https://learn.microsoft.com/en-us/windows-server/networking/technologies/pktmon/pktmon) · Microsoft · Ferramenta integrada que mostra onde e por que os pacotes são descartados em vários pontos da pilha de rede do Windows - [Pktmon command formatting](https://learn.microsoft.com/en-us/windows-server/networking/technologies/pktmon/pktmon-syntax) · Microsoft · Integrada como pktmon.exe no Windows 10 e no Windows Server 2019 (1809 ou superior) - [TCP improvements in the Windows network stack (IETF 98 TCPM)](https://datatracker.ietf.org/meeting/98/materials/slides-98-tcpm-tcp-improvements-in-windows-01) · Microsoft · TLP e RACK ligados por padrão no Windows 10 Anniversary Update (1607) e no Server 2016 (conexões com RTT acima de 10 ms); quando só resta um pacote, o TLP leva em conta o ACK atrasado de 200 ms - [Algorithmic improvements boost TCP performance on the Internet](https://techcommunity.microsoft.com/blog/networkingblog/algorithmic-improvements-boost-tcp-performance-on-the-internet/2347061) · Microsoft · TLP padrão a partir do Windows Server 2016, o RACK novo, que recupera até retransmissões perdidas, incluído no Server 2022, PRR padrão a partir do Windows 10 1903 - [TcpMaxConnectRetransmissions](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc938209(v=technet.10)) · Microsoft · Retransmissão de SYN no Windows antigo: 2 vezes, começando em 3 segundos e dobrando ### #owners - [RFC 4787: Network Address Translation (NAT) Behavioral Requirements for Unicast UDP](https://www.rfc-editor.org/rfc/rfc4787) · IETF · O mapeamento NAT é sempre renovado por pacotes que saem de dentro (REQ-6), e a renovação por pacotes que chegam de fora é opcional (para UDP). Por isso, quem envia o heartbeat é o cliente - [RFC 5382: NAT Behavioral Requirements for TCP](https://www.rfc-editor.org/rfc/rfc5382) · IETF · O NAT pode apagar sessões TCP ociosas, e o timeout de inatividade recomendado é de pelo menos 2 horas e 4 minutos (a configuração pode variar conforme o equipamento) - [Amazon EC2 security group connection tracking](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html) · AWS · Timeout de inatividade TCP do rastreamento de conexões do grupo de segurança (350 segundos nos tipos de instância Nitro v6, 5 dias nos demais, ajustável de 60 segundos a 5 dias), recomendação de keepalive abaixo de 5 minutos, 350 segundos para TCP que passa pelo NLB - [Control subnet traffic with network access control lists](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html) · AWS · A ACL de rede não guarda estado (não há rastreamento de conexões), então o tráfego de resposta também precisa ser liberado por regra - [Monitor network performance for ENA settings on your EC2 instance](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html) · AWS · Contadores de excesso de limite de rastreamento de conexões e de pacotes por segundo da instância (conntrack_allowance_exceeded, pps_allowance_exceeded) - [listen(2) — Linux manual page](https://man7.org/linux/man-pages/man2/listen.2.html) · Linux man-pages · O argumento backlog do listen é o tamanho real da fila e, se for maior que o somaxconn, é cortado para esse valor (padrão 4096 a partir do 5.4) - [IP Sysctl](https://docs.kernel.org/networking/ip-sysctl.html) · Linux kernel · somaxconn (teto do backlog do listen), tcp_max_syn_backlog, tcp_syncookies (padrão 1, recurso usado quando a fila de SYN estoura), tcp_keepalive_time (padrão de 2 horas) - [SNMP counter](https://docs.kernel.org/networking/snmp_counter.html) · Linux kernel · Quando a fila de accept enche, os SYNs são descartados e TcpExtListenOverflows e TcpExtListenDrops aumentam - [Netfilter Conntrack Sysfs variables](https://docs.kernel.org/networking/nf_conntrack-sysctl.html) · Linux kernel · Cálculo da utilização do conntrack com nf_conntrack_count e nf_conntrack_max - [Control Group v2](https://docs.kernel.org/admin-guide/cgroup-v2.html) · Linux kernel · nr_throttled no cpu.stat: número de vezes em que o contêiner sofreu throttling pelo limite de CPU - [proc_stat(5) — Linux manual page](https://man7.org/linux/man-pages/man5/proc_stat.5.html) · Linux man-pages · steal no /proc/stat: tempo em que outro SO usou a CPU em ambiente virtualizado - [RFC 2992: Analysis of an Equal-Cost Multi-Path Algorithm](https://www.rfc-editor.org/rfc/rfc2992) · IETF · O ECMP escolhe o caminho pelo hash dos campos de cabeçalho que identificam o fluxo (o mesmo fluxo segue o mesmo caminho; fluxos diferentes podem seguir caminhos diferentes) - [mtr(8) manual page source](https://raw.githubusercontent.com/traviscross/mtr/master/man/mtr.8.in) · mtr · Medição de rota com o mesmo protocolo e a mesma porta do jogo (-T, -u, -P) ### #l-server-proc - [VALORANT's 128-Tick Servers](https://www.riotgames.com/en/news/valorants-128-tick-servers) · Riot Games · Orçamento do tick: a 128 ticks, cada frame precisa terminar em 7,8125 ms; medir o tempo do frame por subsistema e dividir o orçamento entre eles - [Introducing Time Dilation (TiDi)](https://www.eveonline.com/news/view/introducing-time-dilation-tidi) · CCP Games · A simulação física do EVE Online atualiza uma vez por segundo e, sob sobrecarga, desacelera o relógio do jogo para reduzir proporcionalmente a carga ligada ao tempo - [HED-GP Technical Retrospective: What a HED-ache](https://www.eveonline.com/news/view/what-a-hed-ache) · CCP Games · Limite inferior de 10% para o Time Dilation; o envio O(n²), em que a ação de cada um dos n jogadores é avisada aos n, é o fator que limita as grandes batalhas - [Handling variation in time](https://docs.unity3d.com/Manual/time-handling-variations.html) · Unity · Modelo da simulação de tick: quando o avanço em intervalo fixo atrasa, as etapas de recuperação rodam todas juntas (avanço rápido), e o tempo que passa do limite é descartado, deixando o tempo do jogo mais lento (câmera lenta) - [Comparing Interest Management Algorithms for Massively Multiplayer Games](https://www.sable.mcgill.ca/~clump/papers/boulanger-06-comparing.pdf) · ACM · Artigo do NetGames 2006 (versão pública dos autores). Comparar a distância de todos os pares não escala quando o número de jogadores cresce; dividindo em grade, basta verificar as células vizinhas - [Replication Graph in Unreal Engine](https://dev.epicgames.com/documentation/en-us/unreal-engine/replication-graph-in-unreal-engine) · Epic Games · Dividir o mundo em grade e escolher os destinatários pela lista de cada célula poupa CPU do servidor mesmo com muitos jogadores e atores - [Amdahl's Law in the Multicore Era](https://research.cs.wisc.edu/multifacet/papers/ieeecomputer08_amdahl_multicore.pdf) · IEEE · Teto de vazão na simulação de locks: se a fração que só pode ser feita um de cada vez é 1−f, o ganho de velocidade não passa de 1/(1−f) - [Runtime locking correctness validator](https://docs.kernel.org/locking/lockdep-design.html) · Linux kernel · Deadlock na simulação de locks: pegar dois locks em ordens opostas gera espera circular e deadlock - [Liveness, Readiness, and Startup Probes](https://kubernetes.io/docs/concepts/workloads/pods/probes/) · Kubernetes · Watchdog na simulação de locks: um teste de liveness detecta o deadlock e reinicia; por padrão, verifica a cada 10 segundos e reinicia após 3 falhas seguidas (cerca de 30 segundos) - [ASP.NET Core Best Practices](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/best-practices) · Microsoft · Chamadas síncronas: acesso a dados e I/O devem ser chamados de forma assíncrona; chamadas bloqueantes levam ao esgotamento do pool de threads e a respostas lentas ### #l-infra - [Site Reliability Engineering, Chapter 22: Addressing Cascading Failures](https://sre.google/sre-book/addressing-cascading-failures/) · Google · Falha em cascata: como um backend lento prende threads e recursos das camadas da frente e a falha se espalha por retries, falhas de health check e reinícios com cache vazio, e como responder - [Circuit Breaker Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker) · Microsoft Azure · Estados fechado, aberto e meio aberto do circuit breaker e o critério de número de falhas; com timeout longo, as threads ficam presas até o circuito abrir - [Bulkhead Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead) · Microsoft Azure · Isolar recursos por funcionalidade e por destino de chamada, para que a falha em um ponto não se espalhe - [Timeouts, retries, and backoff with jitter](https://d1.awsstatic.com/builderslibrary/pdfs/timeouts-retries-and-backoff-with-jitter.pdf) · AWS · Amazon Builders' Library. Liberar recursos com timeouts, limitar o número de retries e adicionar jitter - [The Unique Architecture behind Amazon Games’ Seamless MMO New World](https://aws.amazon.com/blogs/gametech/the-unique-architecture-behind-amazon-games-seamless-mmo-new-world/) · AWS · Exemplo de arquitetura de servidores de MMO: servidor de entrada, servidores de simulação por célula da grade (hubs), pool de servidores compartilhados para sessões, BD para guardar o estado - [Working with DB instance read replicas](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ReadRepl.html) · AWS · Atraso de replicação na simulação da arquitetura de servidores: réplicas de leitura são atualizadas de forma assíncrona e podem devolver dados antigos - [Site Reliability Engineering, Chapter 20: Load Balancing in the Datacenter](https://sre.google/sre-book/load-balancing-datacenter/) · Google · Deploy e reinício: desviar as novas requisições em estado lame duck antes de encerrar, aquecer logo após reiniciar - [Amazon EC2 Auto Scaling lifecycle hooks](https://docs.aws.amazon.com/autoscaling/ec2/userguide/lifecycle-hooks.html) · AWS · Ao aumentar ou reduzir a escala, deixar as instâncias em espera para terminar tarefas de preparação e limpeza (até 1 hora por padrão) - [systemd.service(5) — Linux manual page](https://man7.org/linux/man-pages/man5/systemd.service.5.html) · systemd · Watchdog na simulação da arquitetura de servidores: encerra e reinicia automaticamente o serviço cujo sinal de vida parou ## Formatos de gráfico - **Picos em intervalos regulares** (`periodic`): Fica baixo normalmente e sobe em intervalos iguais: a cada tantos segundos, a cada tantos minutos ou na hora cheia. - **Picos aleatórios** (`random`): Sobe de forma irregular, sem intervalo fixo, e logo volta ao normal. - **Degrau a partir de um momento** (`step`): A partir de um momento específico, como um patch, uma mudança de configuração ou de rota, sobe um degrau e fica lá. - **Subida lenta** (`ramp`): Sobe aos poucos ao longo de horas ou dias. Cresce junto com o tempo ligado. - **Dente de serra** (`sawtooth`): Sobe devagar e cai de uma vez no momento de um reinício ou limpeza, repetidamente. - **Alto só em certos horários** (`peak`): Forma uma elevação só no mesmo horário todo dia, como no pico da noite. - **Sobe com a carga** (`load`): Quando aumentam os jogadores simultâneos ou a quantidade de gente reunida num mesmo lugar, sobe ainda mais rápido que eles. - **Achata ao bater no limite** (`ceiling`): A vazão ou o número de conexões chega a um valor e não passa dele. A partir daí, crescem as esperas e os erros. - **Sempre alto desde o início** (`high`): Fica alto o tempo todo, sem picos. É o caso de causas estruturais, como distância, rota e design. - **Alto só em alguns** (`outlier`): A maioria está normal, e só certos jogadores, regiões, operadoras ou dispositivos ficam altos. - **Lacuna e depois tudo junto** (`gap`): O volume recebido fica em zero por um tempo e depois chega tudo de uma vez. - **Queda de conexões em massa** (`drop`): O número de conexões despenca ou o número de desconexões dispara de uma vez. - **Pico logo após abrir ou manutenção** (`surge`): Dispara logo depois que o servidor abre ou que um evento começa, e vai baixando aos poucos. ## Procedimentos por situação ### Lag depois de um patch Quando os reports de lag aumentam a partir de um patch ou deploy específico. Use quando chegam vários reports do tipo “está estranho desde a última atualização” ou quando um gráfico sobe em degrau a partir de um certo momento e fica nesse patamar. 1. **Defina o horário de início e reúna todas as mudanças feitas antes e depois**: Encontre o momento em que os reports começaram a se acumular e o momento em que o gráfico subiu em degrau, e anote, sem deixar nada de fora, as mudanças aplicadas antes e depois. Inclua patches do cliente, deploys do servidor, mudanças de configuração, alterações de schema do BD (DDL) e reinícios, trabalhos de rede e de firewall e trocas de infraestrutura (tipo de instância, kernel, drivers). Se a cada deploy você marcar uma linha vertical em todos os gráficos com o recurso de anotações (annotation) da ferramenta de monitoramento, esta etapa termina rápido. Se o patch do jogo e um trabalho de infraestrutura entraram na mesma janela de manutenção, mantenha os dois como suspeitos. Quem acionar primeiro: as duas equipes que aplicaram mudanças, desenvolvimento e infraestrutura. (causas: in-deploy, so-os-update, db-ddl-lock, db-plan-flip, db-cold-cache) 2. **Separe por escopo: build, dispositivo, servidor, região**: Veja em qual dimensão o problema se concentra. Se só quem está na build nova vai mal, suspeite primeiro do cliente; se só um SO, uma placa de vídeo ou um dispositivo específico vai mal, do desempenho do cliente ou do driver; se só um servidor, canal ou zona, do servidor; se só um país ou operadora, da rota de rede; se todo mundo piorou ao mesmo tempo, de um recurso compartilhado (BD, load balancer, gateway) ou do deploy de servidor que acabou de sair. Se a telemetria do cliente tem o número da build, coloque lado a lado a build antiga e a nova: ping, FPS, picos de frame time e número de desconexões. Se o ping ficou igual e só o FPS piorou, isso aponta mais para o desempenho do cliente do que para a rede. Quem acionar primeiro: se o problema se concentra em build ou dispositivo, equipe de desenvolvimento (cliente); em servidor ou canal, equipe de desenvolvimento (servidor) quando as métricas do host estão normais, ou equipe de infraestrutura (servidores/SO) quando não estão; em país ou operadora, equipe de infraestrutura (rede). (causas: cg-hitch, cg-sync-load, co-vram, cg-crash) 3. **Compare a versão nova e a antiga no mesmo horário**: Comparar só o antes e o depois do deploy mistura variações de dia da semana, horário e eventos e atrapalha a análise. Se possível, suba a versão nova primeiro em alguns servidores (canário) e compare lado a lado com servidores da versão antiga no mesmo horário (grupo de controle): tempo de tick p50 e p99, número de estouros do tick, CPU, memória e taxa de erros. Se o deploy já foi para todos, compare com o mesmo dia da semana e o mesmo horário da semana passada. A média do servidor inteiro esconde problemas de alguns servidores ou zonas, então separe por servidor e por zona. Quem acionar primeiro: equipe de desenvolvimento (servidor). (causas: sp-tick-overrun, mem-alloc, mem-leak, sp-broadcast) 4. **Compare o perfil do tráfego antes e depois**: Mesmo sem conhecer o código do servidor, dá para confirmar pelos valores visíveis na rede se o patch mudou o formato do tráfego. Compare antes e depois: pacotes por segundo (pps) e bytes por jogador, tamanho médio e máximo dos pacotes, número de conexões e tamanho do burst de envio que sai de uma vez a cada tick. Se os pacotes UDP começaram a passar do MTU do caminho (em geral 1.500 bytes), acontece fragmentação IP. Basta perder um fragmento para perder o pacote inteiro, e alguns NATs e firewalls descartam todos os fragmentos. Para jogadores que passam por um trecho com MTU menor (túnel, VPN), só os pacotes grandes somem. Se o pps aumentou, verifique se ele não bateu no limite de PPS da instância na nuvem ou no limite de processamento do firewall ou do equipamento de proteção contra DDoS. Quem acionar primeiro: se o perfil mudou, equipe de desenvolvimento (servidor), com as evidências anexadas; se ele continua igual e só a perda de pacotes e as retransmissões aumentaram, equipe de infraestrutura (rede). (causas: sp-patch-traffic, sk-fragment, rt-mtu, nic-cloud-pps, rt-appliance-pps, rt-burst) 5. **Compare os tipos e a quantidade de queries do BD antes e depois**: Se a latência do BD subiu, verifique primeiro se o número de queries (QPS) subiu junto. O pg_stat_statements do PostgreSQL e o resumo por digest do Performance Schema do MySQL agrupam como um só tipo as queries que diferem apenas nos valores e somam o número de execuções e o tempo total. Comparando o ranking das principais queries antes e depois do patch, aparecem as queries novas, as que passaram a rodar várias vezes mais (N+1) e as que leem a tabela inteira sem índice (no MySQL, a coluna SUM_NO_INDEX_USED). Quem acionar primeiro: se o QPS ou o formato das queries mudou, equipe de desenvolvimento (servidor); se as queries são as mesmas e só a latência aumentou, equipe de infraestrutura (BD: plano de execução, IOPS, locks). (causas: db-no-index, db-login-storm, db-plan-flip, db-cache-stampede) 6. **Separe as camadas com métricas do host e do processo do servidor**: Mesmo sem acesso ao código, use os valores visíveis no SO para separar o que acontece dentro do servidor do que acontece no host. Se a fila de recepção do socket do servidor (Recv-Q) está acumulando, o processo do servidor não está lendo a tempo (tick parado, GC, locks); se uma única thread está em 100%, é gargalo de thread única; se o tempo de pausa no log do GC aumentou, o padrão de uso de memória mudou. Verifique também se o deploy não saiu com o nível de log elevado, aumentando as escritas de log. Se, ao contrário, aumentaram o CPU steal, o throttling ou os descartes na NIC, verifique a infraestrutura alterada no mesmo horário (tipo de instância, kernel, limites do contêiner). Quem acionar primeiro: para sinais de dentro do processo, equipe de desenvolvimento (servidor); para sinais do host, equipe de infraestrutura (servidores/SO). (causas: mem-gc, sp-hotzone, dk-sync-log, so-cpu-quota, so-steal, so-os-update) 7. **Reverta para confirmar e registre o resultado**: Reverta a mudança mais suspeita só em alguns servidores ou para alguns jogadores (rollback, desligar a feature flag), ou volte a configuração ao valor anterior, e veja se o sintoma some junto. Se só o lado revertido melhora, a causa está confirmada. A reversão também pode deixar tudo lento por um tempo, por causa dos reinícios e do cache frio; se não for urgente, faça em um horário de pouco movimento. Anote o resultado no registro do incidente, com o ID da causa, e leve os limites de tamanho de pacote, número de queries e tempo de tick para a checklist pré-deploy do próximo patch. Quem acionar primeiro: a equipe que fez a mudança. (causas: in-deploy, db-cold-cache) ### Lançamento em um novo país ou região Quando o jogo é lançado em um novo país ou quando se adiciona uma nova região ou data center. Use tanto na checagem antes da abertura quanto para investigar reports do tipo “na Coreia está tudo bem, só os jogadores do país novo estão com lag”. 1. **Meça a qualidade da rota por operadora local antes da abertura**: Para cada operadora importante (ASN) do país-alvo, meça a distribuição do tempo de ida e volta (RTT), o jitter e a perda de pacotes até os locais candidatos para os servidores do jogo. Uma média única esconde as diferenças entre operadoras; por isso, veja a mediana e o percentil 95 de cada operadora, separando o pico da noite e a madrugada. A rede pública de medição RIPE Atlas permite escolher país e ASN e disparar ping e traceroute a partir de probes no mundo todo; também dá para subir uma VM temporária na região candidata e medir de lá. Como equipamentos no caminho às vezes limitam as respostas ICMP, meça também, se possível, com o mesmo protocolo e a mesma porta do jogo. Se só uma operadora passa por uma cidade bem mais distante, o problema é de peering ou de rota. As operadoras escolhem as rotas pelo custo, mais do que pela latência, e por isso até destinos próximos podem fazer desvios longos. Quem acionar primeiro: equipe de infraestrutura (rede); se a rota for problema do lado da operadora, externo (operadora, IX). (causas: isp-distance, isp-routing, isp-peak, isp-cable) 2. **Compare as medições com os limites que o design do jogo aguenta**: Compare o RTT e o jitter medidos com as janelas de tempo do jogo (tempo de reação para esquiva, parry etc.), o limite da compensação de lag, o tamanho do buffer de interpolação e o tamanho do buffer de input. Por exemplo, se a janela de parry é de 0,2 s, para clientes das operadoras em que a latência de ida e volta mais o buffer de interpolação passa disso, a reação chega atrasada mesmo quando o jogador reage a tempo. Se a compensação de lag for ampliada para cobrir esses casos, aumentam os reports de quem é atingido dizendo “tomei dano atrás da parede”. Se muitas operadoras passam do limite, a equipe de infraestrutura avalia colocar regiões ou PoPs de borda mais perto, e a equipe de desenvolvimento revisa os valores de janela de tempo, interpolação e compensação de lag. A tabela de referência está no capítulo “Mesmo ping, sensação diferente: modelos de sincronização” deste guia. Quem acionar primeiro: equipe de desenvolvimento (servidor e cliente: limites do design) e equipe de infraestrutura (rede: localização de regiões e PoPs). (causas: sy-short-window, sy-no-lagcomp, sy-lagcomp-overreach, cg-no-buffer) 3. **Verifique o MTU e se o UDP passa**: Confirme se o maior pacote do jogo atravessa inteiro as redes locais. Envie pings de vários tamanhos com a flag de não fragmentar (DF) para medir o MTU do caminho e veja se há trechos com MTU menor que 1.500 bytes, como PPPoE, túneis ou rede móvel. O padrão para transportes de datagramas como o UDP (RFC 8899) recomenda 1.200 bytes em IPv4 como tamanho básico que passa pela maioria dos caminhos; se o maior pacote do jogo for maior que isso, defina com a equipe de desenvolvimento como reduzi-lo ou dividi-lo. Confirme também se o UDP ou as portas do jogo são bloqueados ou têm a velocidade limitada em Wi-Fi público, redes corporativas e algumas operadoras, e se existe um caminho alternativo (TCP, porta 443) para quando houver bloqueio. Quem acionar primeiro: equipe de infraestrutura (rede) e equipe de desenvolvimento (servidor: tamanho dos pacotes). (causas: dc-mtu, rt-mtu, sk-fragment, isp-udp-block, hn-captive, isp-shaping) 4. **Meça o timeout de inatividade do NAT e do CGNAT e ajuste o intervalo do heartbeat**: Meça em quanto tempo os roteadores domésticos e as redes móveis (CGNAT) do país apagam o mapeamento de uma conexão UDP ociosa. Em cada teste, o dispositivo de teste envia um pacote ao servidor para criar o mapeamento e depois não envia mais nada; o servidor manda um pacote ao dispositivo depois de um tempo predefinido (30 s, 60 s, 120 s …). O tempo a partir do qual o dispositivo deixa de receber esse pacote é o timeout de inatividade daquela rede. A especificação (RFC 4787) diz que um mapeamento UDP não deve expirar antes de 2 minutos e recomenda um valor padrão de 5 minutos ou mais, mas o valor varia muito entre equipamentos, e alguns apagam o mapeamento antes disso. O mapeamento só é renovado com certeza por pacotes que saem do dispositivo; por isso, quem envia o heartbeat deve ser o cliente, e o intervalo deve ser no máximo metade do menor valor entre o medido e os timeouts de inatividade do load balancer e do grupo de segurança da nuvem. Quem acionar primeiro: equipe de desenvolvimento (cliente: intervalo do heartbeat; servidor: valores de timeout) e equipe de infraestrutura (configuração do load balancer e dos grupos de segurança). (causas: hn-nat, isp-cgnat, rt-mapping, dc-lb-idle, dc-cloud-conntrack) 5. **Verifique os serviços externos e os equipamentos de segurança usados no país**: Confirme se o login nas plataformas locais, os pagamentos e a verificação de identidade respondem na velocidade normal, se o DNS local resolve corretamente os endereços dos servidores de login e de patch e se a CDN entrega os patches a partir de um ponto de presença próximo do país. Verifique se as faixas de IP do novo país não caem nas regras de bloqueio por país e nos limites de taxa da proteção contra DDoS e do firewall e, principalmente, se faixas de CGNAT, em que vários assinantes dividem um único IP, não estão sendo bloqueadas de uma vez. Quem acionar primeiro: equipe de infraestrutura (equipamentos de segurança, DNS, CDN); externo (plataformas, empresas de pagamento, operadoras). (causas: in-external, isp-dns, dc-ddos, isp-cgnat) 6. **Depois da abertura, analise por país e por ASN**: Associe país e ASN aos IPs de cliente nos logs de conexão e do load balancer e acompanhe, por país e por operadora, o RTT, as retransmissões, o número de desconexões e os motivos (timeout de heartbeat, RST, kick pelo servidor). Bancos de dados gratuitos como o MaxMind GeoLite ASN convertem um IP em ASN e nome da organização; para cumprir as regras locais de privacidade, guarde os IPs reduzidos a /24 ou ao ASN. Se o problema se concentra em um único ASN, verifique primeiro a rota daquela operadora (equipe de infraestrutura, externo); se o país novo inteiro vai mal, a distância e os limites do design (equipe de infraestrutura, equipe de desenvolvimento); se piora só à noite, o congestionamento no peering. Se só alguns jogadores têm ping sempre alto, verifique com a equipe de desenvolvimento (servidor) se eles não estão sendo alocados em uma região distante por erro de GeoIP, por VPN ou pela alocação com base no líder da party. Se o monitoramento sintético está normal e só os jogadores vão mal, o problema está no ambiente do jogador ou no cliente. (causas: isp-peak, isp-routing, rt-queue-drop, pt-isp-validation, in-region-match) 7. **Verifique o impacto dos jogadores distantes sobre os outros**: Quando aumentam os jogadores que se conectam de longe, o efeito vai além da tela deles. Os comandos de quem tem lag chegam todos de uma vez, e na tela dos outros só aquele personagem se move em avanço rápido; ao cair nas verificações de velocidade e cooldown do servidor, surgem rubber banding e skills recusadas. Em mecânicas de party, a reação atrasada de um único jogador lento vira falha da party inteira, e no lockstep todos esperam o mais lento. Depois do lançamento no país novo, verifique se aumentaram, entre os jogadores que já estavam no jogo, os reports do tipo “Só um personagem parece estranho” e defina com a equipe de desenvolvimento o buffer de input, as tolerâncias da validação e a separação do matchmaking por região. Quem acionar primeiro: equipe de desenvolvimento (servidor). (causas: pt-slow-burst, pt-isp-validation, pt-raid-member, sy-lockstep) ## Incidentes reais ### eve-hedgp-2014 · CCP Games 2014: EVE Online: sobrecarga do servidor na grande batalha de frotas em HED-GP - O que aconteceu: Na grande batalha de frotas no sistema estelar HED-GP, analisada em uma retrospectiva de janeiro de 2014, o servidor ficou muito sobrecarregado. O Time Dilation (recurso que desacelera o tempo do jogo em caso de sobrecarga) chegou ao limite mínimo de 10% e o campo de batalha inteiro entrou em câmera lenta, mas a carga continuou se acumulando. O atraso no processamento das paradas e dos ciclos repetidos dos módulos (Dogma Lateness) chegou a um pico de 193 segundos de tempo de jogo, cerca de 32 minutos em tempo real. Na batalha de 6VDT, em julho de 2013, de porte quase igual, o máximo tinha sido 42 segundos (cerca de 7 minutos em tempo real). - Causa: A CCP deixou claro que não tinha certeza, porque as ferramentas de análise de desempenho adicionam carga por si mesmas e não são executadas nessas situações, e apontou duas causas prováveis. A primeira foi a carga não processada que continuou se acumulando à medida que a batalha se prolongava. A segunda foi o aumento do uso de drones: o número de drones distintos lançados durante a batalha foi de 21.123 em 6VDT e de 38.852 em HED-GP, 84% a mais. As mensagens que avisam todos os que veem a ação de um jogador crescem com o quadrado do número de jogadores (O(n²)), e os drones geram mais mensagens por ataque. O código com que os drones escolhem o alvo também percorre com frequência todos os alvos atacáveis do mesmo campo de batalha, e por isso o custo cresce perto de n². - Lições: Quando a demanda de processamento de uma área lotada passa do limite, a área inteira entra em câmera lenta; quanto mais longa a batalha, mais trabalho atrasado se acumula e maior fica o input lag. Os sinais para verificar são o tempo de tick e o trabalho acumulado do servidor (nó) responsável pela área, junto com o número de jogadores e de entidades; o que caracteriza o caso é que as outras áreas continuam normais. O responsável principal é a equipe de desenvolvimento (servidor), e os pontos a corrigir são o alcance de quem precisa ser avisado de cada ação e o custo da busca de alvos da IA. Desacelerar o tempo do jogo não elimina a sobrecarga, mas faz todos ficarem lentos na mesma velocidade e impede que só algumas ações fiquem atrasadas indefinidamente. - Causas relacionadas: sp-broadcast, sp-tick-overrun, sp-queue, sp-hotzone - Fonte original: [CCP Games](https://www.eveonline.com/news/view/what-a-hed-ache) ### riot-direct-2015 · Riot Games 2015: Desvios no tráfego do League of Legends e o Riot Direct - O que aconteceu: Artigo técnico em que a Riot Games explicou por que a internet não é adequada para jogos em tempo real. Em um caso real reportado por um jogador de League of Legends, o tráfego deveria ir direto de San Francisco a Portland, mas passava por Los Angeles, Denver e Seattle: o que levaria 14 ms em linha direta levava 70 ms. A Riot explicou que, quando um roteador fica sobrecarregado e descarta pacotes, os outros campeões parecem pular pela tela e os projéteis parecem teleportar. - Causa: A Riot apontou as rotas e os roteadores como causa. Provedores de backbone e operadoras mandam o tráfego pela rota mais barata, mesmo quando existe uma rota com menos latência. Quando a rota definida pelo BGP faz um desvio longo, o número de roteadores no caminho também aumenta. A carga de processamento de um roteador é proporcional ao número de pacotes, independentemente do tamanho deles. Pacotes de jogo têm por volta de 55 bytes; para a mesma quantidade de dados, são 27 vezes mais pacotes que com pacotes de 1.500 bytes, e eles enchem o buffer de entrada do roteador proporcionalmente mais rápido. Segundo a Riot, muitos roteadores descartam primeiro os pacotes UDP quando ficam sobrecarregados. Como solução, a Riot criou o Riot Direct, uma rede própria com roteadores em 10 grandes pontos de interconexão da internet nos EUA, conectada diretamente (peering) com o maior número possível de operadoras. Segundo a parte 2, a proporção de jogadores com ping abaixo de 80 ms subiu de 31% para 50% em pouco mais de 9 meses e chegou a 80% da noite para o dia depois que os servidores do jogo foram transferidos para Chicago. - Lições: Se, mesmo dentro de um país, só os clientes de uma operadora têm ping muito mais alto, suspeite da rota. Os sinais para verificar são a distribuição do RTT por operadora (ASN) e as cidades por onde o traceroute passa. O responsável principal é a equipe de infraestrutura (rede), e a correção vem de peering direto com as operadoras, conexão a um IX (ponto de troca de tráfego) e escolha da localização dos servidores. A política de rotas do lado da operadora precisa ser negociada com a própria operadora (externo). O caso também mostra que só levar os servidores para perto do centro da distribuição dos jogadores já faz grande diferença. - Causas relacionadas: isp-routing, isp-distance, rt-queue-drop - Fonte original: [Riot Games](https://www.riotgames.com/en/news/fixing-internet-real-time-applications-part-i) ### riot-edge-2020 · Riot Games 2020: Sobrecarga de hosts de borda nos servidores do League of Legends na Europa e no Brasil - O que aconteceu: No fim de fevereiro de 2020, os servidores EUW, EUNE e BR do League of Legends tiveram várias quedas, e o número de partidas novas caiu muito. Os serviços de backend, como matchmaking e servidores de jogo, estavam todos com status normal, mas quase não chegava tráfego a eles. A Riot adiou em uma semana o modo de torneio (Clash) para não abri-lo em clusters que podiam estar instáveis. A retrospectiva não informa quanto tempo durou cada queda. - Causa: Três problemas se somaram. Requisições a um serviço eram montadas de forma errada, falhavam sempre em certos casos e eram repetidas sem parar, o que fez o volume de requisições explodir. Uma incompatibilidade conhecida entre o sistema de contêineres e a versão do SO causava vazamento de memória dentro do SO; a atualização só tinha sido concluída em cerca de 60% de todo o ambiente de contêineres da Riot, e nos clusters da Europa e da América Latina ainda estava em andamento. Os contêineres de borda, que recebem o tráfego da internet, filtram e encaminham ao backend, ficavam em hosts diferentes dentro de um mesmo shard (grupo de servidores), mas nada impedia que contêineres de shards diferentes caíssem no mesmo host; em todas as quedas, contêineres de borda de pelo menos três shards estavam concentrados em um único host. A explosão de retries caiu sobre esse host, e o vazamento de memória o fez parar. - Lições: Se todos os serviços de backend respondem “está tudo normal, mas não chega tráfego”, verifique o que fica na frente deles (borda, gateway, load balancer). Os sinais para verificar são a concentração de conexões de entrada por host e a taxa de falhas e retries de uma requisição específica. O responsável principal é a equipe de desenvolvimento (servidor: requisições malformadas e estratégia de retry); as regras de posicionamento dos contêineres, a atualização do SO e os alertas de desbalanceamento ficam com a equipe de infraestrutura (servidores/SO). A Riot corrigiu o código das requisições, mudou a lógica de retry para evitar picos repentinos de tentativas e, até implementar a distribuição entre shards, manteve alertas de desbalanceamento. - Causas relacionadas: in-gateway, in-cascade - Fonte original: [Riot Games](https://www.leagueoflegends.com/en-gb/news/riot-games/incident-report-recent-outages-in-europe-brazil/) ### riot-euw-2021 · Riot Games 2021: Queda de 5 horas no EUW do League of Legends: um BD auxiliar parou o servidor inteiro - O que aconteceu: Em 22 de janeiro de 2021, o servidor EUW do League of Legends ficou pouco mais de 5 horas sem funcionar direito. As métricas de jogadores logados e de jogadores em partida pararam ao mesmo tempo e, entre os dois reinícios, os logins aumentavam, mas quase nenhuma partida começava. - Causa: O servidor primário de um BD que cuidava de uma função pouco importante teve uma falha de hardware, e esse BD estava sem failover automático para o servidor reserva. Cada BD tinha seu próprio pool de conexões, mas todos os pools usavam o mesmo pool de threads; as tarefas enviadas ao BD com defeito não terminavam e ficavam segurando threads, até acabarem as threads de todo o sistema. No meio da enxurrada de alertas, a equipe suspeitou primeiro de um ataque de rede malicioso sofrido pouco antes e de um trabalho de hardware em outra região, e o alerta do BD com defeito só foi notado cerca de 1 hora depois. Como todos os sistemas rodavam em uma única JVM, quando o GC passou a parar o processo por alguns segundos sob a carga de reconexões depois do reinício, também surgiram grandes lacunas na coleta de métricas. A fila de login também não respeitava o limite configurado, e a entrada de jogadores ficou irregular. - Lições: Até um BD auxiliar considerado pouco importante pode parar tudo por meio de um recurso compartilhado, como um pool de threads. Os sinais para verificar são o número de requisições pendentes por BD, a utilização do pool de threads e uma proporção de partidas iniciadas baixa demais em relação aos logins. Os responsáveis são a equipe de desenvolvimento (servidor: isolamento dos pools de threads e timeouts) e a equipe de infraestrutura (BD: failover automático). Quando os alertas se acumulam, é fácil suspeitar primeiro do problema mais recente (um ataque, por exemplo); descarte as hipóteses uma a uma na ordem de diagnóstico (escopo → momento → camada). Depois do reinício, verifique também se a fila de login está limitando a entrada como configurado. - Causas relacionadas: sp-threadpool, db-failover, in-cascade, mem-gc - Fonte original: [Riot Games](https://www.riotgames.com/en/news/keeping-legacy-software-alive-case-study) ### roblox-2021 · Roblox 2021: Queda de 73 horas no Roblox: contenção no cluster de service discovery (Consul) - O que aconteceu: Na tarde de 28 de outubro de 2021 (horário do Pacífico), o problema começou com alta carga de CPU em um servidor Consul; às 16:35 o número de jogadores conectados caiu para metade do normal, e depois o serviço inteiro parou. Só às 16:45 de 31 de outubro todos os jogadores conseguiram entrar de novo: 73 horas desde o início do incidente. A Roblox informou que 50 milhões de pessoas usam a plataforma todos os dias. - Causa: A Roblox usa o HashiCorp Consul para service discovery (o recurso com que os serviços encontram o endereço uns dos outros), health checks e armazenamento KV, e um único cluster Consul atendia várias cargas de trabalho ao mesmo tempo. Houve duas causas-raiz. Primeiro, a nova funcionalidade de streaming do Consul, que vinha sendo ampliada havia meses, foi ativada na véspera também no serviço de roteamento de tráfego, e o número de nós desse serviço aumentou 50%; sob uma carga com muitas leituras e muitas escritas, essa funcionalidade gerou contenção em um único recurso compartilhado (um canal Go). Nos servidores dual socket (NUMA) com mais núcleos, colocados no lugar dos antigos durante o incidente, a contenção foi ainda pior. Segundo, o gerenciamento da lista de páginas livres (freelist) do BoltDB, que o Consul usa para gravar o log do Raft, ficou patologicamente lento: cada acréscimo de até 16 kB gravava 7,8 MB no disco. A mediana da latência de escrita no KV, normalmente abaixo de 300 ms, chegou a 2 segundos, e no servidor líder lento também foi observada janela zero (zero window), com o buffer TCP cheio. Como a telemetria dependia do Consul, as métricas necessárias para achar a causa também sumiram. - Lições: Quando um sistema de base do qual vários serviços dependem (service discovery, armazenamento de configuração, autenticação) fica lento, todas as funções param ao mesmo tempo. Os sinais para verificar são a latência de escrita, as trocas de líder e a CPU desse sistema, além de mudanças de configuração feitas pouco antes do incidente. Os responsáveis são as duas equipes: desenvolvimento (servidor) e infraestrutura (servidores/SO). O monitoramento precisa ser separado e não depender do sistema monitorado, para que as métricas continuem visíveis durante um incidente. Na recuperação, os caches estão vazios e receber todo mundo de uma vez pode derrubar tudo de novo; por isso a Roblox controlou pelo DNS a proporção de jogadores que podiam entrar e foi aumentando em passos de cerca de 10%. - Causas relacionadas: in-cascade, sp-lock, rt-zero-window, db-cold-cache - Fonte original: [Roblox](https://about.roblox.com/newsroom/2022/01/roblox-return-to-service-10-28-10-31-2021) ### ffxiv-2021 · Square Enix 2021: FINAL FANTASY XIV: lotação no lançamento da expansão e erros na fila de login - O que aconteceu: A partir do acesso antecipado da expansão Endwalker, em dezembro de 2021, todos os mundos ficaram extremamente lotados. A fila de login ficou longa, e o Error 2002 aparecia com frequência ao entrar pela tela de seleção de personagem ou durante a espera na fila. Também houve quedas de alguns mundos e zonas (Error 3001) e timeouts na fila (Error 4004). Quando o aviso de 11 de dezembro foi publicado, no 8º dia do acesso antecipado, a lotação continuava. - Causa: O Error 2002 aparece em dois casos. O primeiro é quando a fila passa de 17.000 pessoas em um data center lógico: é um limite para evitar que a fila fique longa demais e derrube o servidor de login, e nesse caso o cliente é encerrado por completo. Em 7 de dezembro, equipamentos de reserva da área de desenvolvimento foram colocados nos servidores de lobby para aumentar o limite; esse erro diminuiu, mas a fila ficou ainda mais longa. O segundo caso é quando a conexão do jogador na fila está instável. Com esperas mais longas, aumentaram as quedas breves de conexão por perda de pacotes no caminho pela internet ou por instabilidade no Wi-Fi. O servidor de lobby espera a reconexão por algo entre dezenas de segundos e 1 minuto; quem reconecta dentro desse prazo retoma de onde estava na fila, e quem passa do prazo volta para o fim. A Square Enix informou que a maioria dos reports era desse caso. Por causa da falta de semicondutores, também não dava para aumentar o número de mundos de imediato. - Lições: Quanto mais longa a fila, mais as quedas breves na conexão de quem está esperando viram erros de conexão. Mesmo com a mesma lotação, os erros se concentram em quem usa Wi-Fi ou uma conexão instável, e o caso vira um problema que “só afeta alguns”. Os sinais para verificar são o tamanho da fila, o tempo de espera e, entre os motivos de desconexão, a proporção de quedas durante a espera. O responsável principal é a equipe de desenvolvimento (servidor: limite da fila e tempo de tolerância para reconexão), e a equipe de infraestrutura participa ampliando os servidores de lobby e de mundo. Um tempo de tolerância para reconexão folgado reduz os casos em que uma queda breve na conexão do jogador acaba custando a posição na fila. - Causas relacionadas: in-login-queue, hn-wifi, rt-wireless - Fonte original: [Square Enix](https://na.finalfantasyxiv.com/lodestone/news/detail/6a94b30182b6d963994fdc0b789264ac9f24986f) ### cloudflare-2020 · Cloudflare 2020: Perda de tráfego em algumas cidades por erro de configuração no backbone da Cloudflare - O que aconteceu: É um tipo de falha de infraestrutura que também atinge jogos, porque muitos jogos confiam a web, as APIs e a proteção contra DDoS a provedores de CDN. Em 17 de julho de 2020, das 21:12 às 21:39 (UTC), durante 27 minutos, o tráfego total da rede da Cloudflare caiu cerca de 50%. O impacto se limitou aos pontos de presença de algumas cidades dos EUA, da Europa, da Rússia e do Brasil conectados ao backbone; os outros pontos de presença funcionaram normalmente. - Causa: Uma falha no trecho de backbone Newark–Chicago congestionou o trecho Atlanta–Washington, e um engenheiro alterou a configuração de um roteador para tirar tráfego de backbone de Atlanta. Ele deveria desativar o item de política (term) inteiro, mas desativou só a condição dentro dele (prefix-list); com isso, o roteador de Atlanta passou a anunciar todas as rotas BGP para o backbone inteiro com prioridade mais alta (local-preference 200). Como cada ponto de presença dava prioridade 100 às rotas para os próprios servidores, todo o tráfego dos pontos de presença conectados ao backbone foi parar em Atlanta. Atlanta ficou sobrecarregada, e os pontos de presença afetados ficaram quase sem tráfego para processar. O serviço voltou quando o roteador de Atlanta foi retirado do backbone. A Cloudflare informou que o incidente não teve relação com ataque nem invasão. - Lições: Se só os jogadores de uma cidade ou região sofrem desconexão em massa, ou não conectam e ficam em loading infinito, enquanto os demais jogam normalmente, suspeite primeiro de uma mudança recente na configuração de rotas. No gráfico, a CPU e o tráfego disparam em um único ponto de presença, enquanto os pontos afetados caem para perto de 0. O responsável principal é a equipe de infraestrutura (rede); se a falha for do lado do provedor, o responsável é externo. A Cloudflare decidiu limitar o número de rotas aceitas nas sessões BGP do backbone (maximum-prefix) e ajustou as prioridades para que um ponto de presença não possa puxar o tráfego dos outros. - Causas relacionadas: isp-bgp, rt-path - Fonte original: [Cloudflare](https://blog.cloudflare.com/cloudflare-outage-on-july-17-2020/) ### fastly-2021 · Fastly 2021: Erro global na CDN da Fastly - O que aconteceu: É um tipo de falha de infraestrutura que também atinge jogos, porque muitos jogos distribuem arquivos de patch, launchers e páginas web por CDN. Em 8 de junho de 2021, a partir das 09:47 (UTC), 85% da rede da Fastly passou a devolver erros. Em 49 minutos, 95% da rede voltou ao normal, e o incidente foi resolvido às 12:35. - Causa: Um deploy de software iniciado em 12 de maio continha um bug que era disparado quando uma configuração específica de cliente encontrava uma condição específica. Em 8 de junho, um cliente enviou uma mudança de configuração válida e a condição foi satisfeita. A Fastly detectou o problema em 1 minuto, e a recuperação começou quando a configuração de cliente causadora foi identificada e desativada. O deploy da correção do bug começou no mesmo dia, às 17:25. - Lições: Código que está em produção há semanas também pode virar, de uma hora para outra, uma falha global quando encontra uma condição rara. Do lado do jogo, os sinais para verificar são a taxa de erros HTTP das requisições de patch, launcher e web subindo em todas as regiões ao mesmo tempo e a página de status do provedor de CDN. O que caracteriza o caso é que as conexões de jogo já estabelecidas que não passam pela CDN continuam normais, e só os novos acessos, os downloads de patch e o login pela web ficam bloqueados. O responsável principal é externo (o provedor de CDN); as equipes de desenvolvimento e de infraestrutura deixam pronto um caminho alternativo, como usar mais de uma CDN ou baixar direto do servidor de origem. - Causas relacionadas: in-external - Fonte original: [Fastly](https://www.fastly.com/blog/summary-of-june-8-outage) ### meta-2021 · Meta 2021: Facebook: um único comando no backbone derrubou até o DNS - O que aconteceu: É uma falha de infraestrutura cujas lições valem igualmente para a rede própria e o DNS de uma empresa de jogos. Em 4 de outubro de 2021, os serviços do Facebook (hoje Meta) ficaram inacessíveis no mundo inteiro. O backbone que liga os data centers caiu por completo, e os servidores DNS do Facebook deixaram de ser encontrados a partir da internet. A retrospectiva não informa quanto tempo durou a queda. - Causa: Durante uma manutenção de rotina, um comando enviado para verificar a capacidade do backbone global acabou derrubando, sem querer, todas as conexões do backbone, e a ferramenta de auditoria que deveria bloquear esse tipo de comando não o bloqueou por causa de um bug. Os servidores DNS dos pontos de presença menores estavam configurados para se considerar não saudáveis e retirar seus anúncios BGP quando perdem a comunicação com os data centers; assim, mesmo funcionando, ficaram inalcançáveis pela internet. Caíram tanto os caminhos de acesso habituais quanto o acesso fora de banda (out-of-band), e as ferramentas internas também perderam o DNS; foi preciso mandar engenheiros fisicamente aos data centers, e os procedimentos de segurança tornaram tudo mais lento. Na recuperação, o consumo de energia de cada data center tinha caído dezenas de MW, e a equipe avaliou que religar tudo de uma vez poderia pôr em risco desde a infraestrutura elétrica até os caches; por isso, a carga foi aumentada aos poucos. - Lições: Se, em todas as regiões e em todas as operadoras, os jogadores não conectam ou ficam em loading infinito ao mesmo tempo, verifique primeiro o DNS e as rotas BGP; os servidores do jogo vêm depois. Dá para confirmar isso de fora da empresa, com consultas a DNS externos e informações públicas de rotas BGP. O responsável principal é a equipe de infraestrutura (rede). Verifique com antecedência se o acesso fora de banda reservado para incidentes e as ferramentas internas não dependem do mesmo DNS e da mesma rede e, na recuperação, aumente a carga aos poucos para que as reconexões não cheguem todas de uma vez. - Causas relacionadas: isp-bgp, isp-dns - Fonte original: [Meta](https://engineering.fb.com/2021/10/05/networking-traffic/outage-details/) ### aws-2021 · AWS 2021: Congestionamento na rede interna da AWS us-east-1 - O que aconteceu: É um tipo de falha de infraestrutura que também atinge jogos, porque muitos jogos mantêm servidores, login e dados em nuvem pública. Em 7 de dezembro de 2021, às 07:30 (PST, horário padrão do Pacífico), a rede interna da região do norte da Virgínia (us-east-1) ficou congestionada. A partir das 07:33, aumentaram os erros e a latência da API do EC2, o que dificultou subir novas instâncias (o início de instâncias se recuperou às 14:40); vieram também falhas de login no console, impossibilidade de alterar configurações do Route 53 e atraso e perda parcial de métricas do CloudWatch. Os equipamentos de rede se recuperaram por completo às 14:22. As instâncias EC2 que já estavam rodando e as respostas de DNS existentes não foram afetadas. - Causa: Uma tarefa automática para aumentar a capacidade de um serviço da rede principal provocou um comportamento inesperado em um grande número de clientes da rede interna, e as tentativas de conexão explodiram. Os equipamentos que ligam a rede interna à rede principal ficaram sobrecarregados e a comunicação atrasou; o atraso, por sua vez, aumentou as tentativas de conexão e os retries, e o congestionamento se manteve. Os clientes tinham um backoff que aumenta o intervalo entre requisições em situações assim, mas um defeito latente impediu que ele funcionasse direito. O monitoramento interno também dependia da mesma rede, e a equipe de operações teve de responder sem métricas em tempo real, apoiando-se nos logs. - Lições: Se os retries não aumentam o intervalo entre si, um congestionamento curto vira uma falha de horas. Do lado do jogo, mesmo com os servidores que já rodavam funcionando normalmente, podem ficar bloqueados ao mesmo tempo a criação de novos servidores (autoscaling), o login, o matchmaking e os pagamentos que usam APIs da nuvem, além do monitoramento. Os sinais para verificar são a página de status do provedor de nuvem, a taxa de erros das APIs da nuvem e as falhas ao iniciar instâncias. O responsável principal é externo (o provedor de nuvem); a equipe de desenvolvimento coloca backoff exponencial com intervalo aleatório e limite de tentativas em todos os retries, e a equipe de infraestrutura prepara capacidade de reserva para aguentar mesmo sem conseguir escalar, além de alternativas em outra região. - Causas relacionadas: in-cascade, in-autoscale, in-external - Fonte original: [AWS](https://aws.amazon.com/message/12721/) ### cloudflare-dns-2025 · Cloudflare 2025: Falha no DNS público 1.1.1.1 da Cloudflare - O que aconteceu: Falha de um resolvedor DNS público que os próprios jogadores configuram no dispositivo ou no roteador: é o tipo de incidente em que todos os jogos e serviços ficam bloqueados ao mesmo tempo, mas só para quem usa essa configuração. Em 14 de julho de 2025, das 21:52 às 22:54 (UTC), durante 62 minutos, o resolvedor 1.1.1.1 parou de responder no mundo inteiro. A Cloudflare afirmou que, para muitos usuários, isso significou na prática não conseguir usar nenhum serviço de internet. Foram afetadas as consultas por UDP, TCP e DNS over TLS; o DNS over HTTPS, acessado por nome de domínio, ficou relativamente estável. - Causa: Em 6 de junho, ao preparar a topologia de serviço (a configuração que define em quais pontos de presença cada faixa de IP é anunciada) de outro serviço que seria usado no futuro, a faixa de IP do resolvedor 1.1.1.1 foi incluída por engano nessa configuração. Em 14 de julho, quando a configuração desse serviço foi alterada, o anúncio da faixa do resolvedor, antes feito em todos os pontos de presença, ficou restrito a um único ponto offline, e as rotas BGP foram retiradas no mundo inteiro. A mudança não passou por deploy canário e se espalhou imediatamente por todos os data centers. Às 22:20 a configuração foi revertida e o tráfego voltou a cerca de 77%, mas nesse meio-tempo a configuração de IP necessária tinha sido apagada em cerca de 23% dos servidores de borda, e, por causa da reconfiguração, o serviço só voltou ao normal às 22:54. A Cloudflare informou que foi um erro de configuração interno, sem relação com ataque ou sequestro de BGP (BGP hijacking). - Lições: Se os servidores do jogo e os outros jogadores estão normais, mas alguns jogadores não conectam ao servidor de login ou de patch e ficam em loading infinito, suspeite do DNS que esses jogadores usam. O que caracteriza o caso é que as sessões já conectadas continuam e só as novas conexões falham. Peça ao jogador que troque o DNS ou consulte diretamente o endereço do servidor, e o caso se confirma ou se descarta na hora. O responsável principal é externo (o serviço de DNS ou a operadora); se a equipe de desenvolvimento (cliente) mostrar a falha de resolução de nomes separada dos outros erros, o suporte ao cliente consegue diagnosticar de imediato. - Causas relacionadas: isp-dns, isp-bgp - Fonte original: [Cloudflare](https://blog.cloudflare.com/cloudflare-1-1-1-1-incident-on-july-14-2025/) ### aws-2025 · AWS 2025: Falha de DNS do DynamoDB na AWS us-east-1 e a longa recuperação - O que aconteceu: É um tipo de falha de infraestrutura que também atinge jogos, porque muitos jogos mantêm servidores, login e dados em nuvem pública. De 19 de outubro de 2025, às 23:48, até 20 de outubro, às 14:20 (PDT, horário de verão do Pacífico), a região do norte da Virgínia sofreu impactos em três fases. Até as 02:40 do dia 20, os erros da API do DynamoDB aumentaram; das 02:25 às 10:36, falhou o início de novas instâncias EC2 (os problemas de conexão de algumas instâncias novas só foram resolvidos às 13:50); e das 05:30 às 14:09, aumentaram os erros de conexão em alguns Network Load Balancers (NLB). - Causa: A automação que gerencia o DNS do DynamoDB tinha uma condição de corrida (race condition) latente. Entre os executores que aplicam os planos de DNS em diferentes zonas de disponibilidade (DNS Enactor), um que estava excepcionalmente atrasado sobrescreveu o plano novo com um plano antigo; logo em seguida, a rotina de limpeza de outro executor apagou esse plano antigo, e o registro DNS do endpoint regional (dynamodb.us-east-1.amazonaws.com) ficou vazio. A automação não conseguiu corrigir isso, e a recuperação teve de ser feita manualmente. O sistema de gerenciamento dos servidores físicos do EC2 dependia do DynamoDB, e nesse intervalo expiraram os leases que ele mantinha para cada servidor físico. Depois que o DynamoDB voltou, havia tantos servidores físicos que as tarefas de renovar os leases davam timeout antes de terminar, e os retries voltavam a se acumular, levando a um estado de “colapso por congestionamento” (congestive collapse). A configuração de rede das instâncias recém-criadas se propagava com atraso, os health checks do NLB alternavam entre sucesso e falha, e até nós saudáveis saíam do DNS e voltavam, repetidamente. - Lições: Um erro em um único registro DNS se espalha para outros serviços que dependem daquele serviço e, mesmo depois de resolvida a causa, o trabalho acumulado e a oscilação dos health checks fazem a recuperação levar horas a mais. Do lado do jogo, os servidores que já rodavam aguentam, mas não dá para subir novos servidores e o autoscaling para; com os health checks oscilando, o load balancer acaba tirando servidores saudáveis. Os sinais para verificar são a página de status da nuvem, a taxa de erros das APIs de serviços gerenciados, as falhas ao iniciar instâncias e o número de destinos saudáveis no load balancer. O responsável principal é externo (o provedor de nuvem); a equipe de infraestrutura limita quantos servidores podem sair de uma vez por falha de health check e prepara alternativas em outra região. - Causas relacionadas: in-external, in-cascade, in-autoscale, dc-lb-imbalance, isp-dns - Fonte original: [AWS](https://aws.amazon.com/message/101925/) ## Glossário - **Ping** (Ping, RTT): Tempo que um sinal enviado por você leva para ir até o servidor e voltar (ida e volta). O ping exibido no jogo às vezes inclui também o tempo de espera pelo processamento no servidor. - **Latência** (Latency): Tempo que um pacote leva da saída até a chegada. Como muitas vezes se refere a um só sentido, fica em torno da metade do ping. - **Jitter** (Jitter): Variação no intervalo de chegada dos pacotes. Mesmo com o mesmo ping médio, jitter alto faz a imagem engasgar. - **Pacote** (Packet): Bloco de dados enviado de uma vez pela rede. Normalmente tem no máximo 1.500 bytes; as atualizações de jogo têm de dezenas a centenas de bytes. - **Perda de pacotes** (Packet loss): Quando um pacote enviado some e não chega ao destino. Em jogos que usam TCP, basta 1% para sentir um engasgo a intervalos de alguns segundos a pouco mais de dez segundos; jogos em UDP com interpolação e envio repetido de comandos conseguem esconder perdas de até alguns %. - **Largura de banda** (Bandwidth): Quantidade máxima de dados que a conexão consegue transmitir por segundo (Mbps). É um conceito diferente da rapidez com que os dados chegam (latência). - **Tick** (Tick): Unidade em que o servidor calcula o estado do jogo uma vez. Um servidor de 20 ticks calcula 20 vezes por segundo, a cada 50 ms. - **Tick rate** (Tick rate): Quantos ticks o servidor roda por segundo. Quanto maior, mais rápida a resposta, mas aumentam o custo do servidor e o volume de dados enviados. Para economizar tráfego, a frequência de envio de pacotes às vezes fica abaixo do tick rate. - **Orçamento do tick** (Tick budget): Tempo máximo para terminar um tick. Se ele estoura, o tick seguinte atrasa e o intervalo entre ticks aumenta. - **FPS** (Frames per second): Quantas vezes por segundo a tela é desenhada. A 60 FPS, cada frame tem 16,7 ms. - **Frame time** (Frame time): Tempo gasto para desenhar um frame. Para a sensação de fluidez, os frames que de vez em quando demoram muito pesam mais que o FPS médio. - **Snapshot** (Snapshot): Resumo do “estado atual do jogo” que o servidor envia a cada tick, com posição, vida, status etc. Em geral, só vai o que mudou em relação ao estado que o receptor já tem (compressão delta). - **Interpolação** (Interpolation): Técnica que liga dois snapshots recebidos para o movimento parecer suave. Em troca, mostra um momento um pouco no passado. - **Buffer de interpolação** (Interpolation buffer): Atraso proposital no desenho para permitir a interpolação. É a folga que absorve o jitter e a perda de um ou dois pacotes. Normalmente é o dobro do intervalo entre pacotes (100 ms recebendo 20 vezes por segundo), e alguns jogos o aumentam sozinhos quando o jitter cresce. - **Extrapolação** (Extrapolation, Dead reckoning): Técnica que, quando não chegam pacotes novos, estima onde a entidade estará a seguir com base na última velocidade conhecida. Quando erra, parece teleporte, por isso muitos jogos só extrapolam até uns 0,25 s e param (o padrão da Source Engine é 0,25 s). - **Predição no cliente** (Client-side prediction): Técnica que move seu personagem na hora, sem esperar a confirmação do servidor. - **Reconciliação com o servidor** (Reconciliation): Correção da posição do seu personagem quando o resultado do servidor chega e é comparado com a predição. A partir da posição confirmada pelo servidor, o cliente reaplica os seus comandos que ainda não foram confirmados. Se a diferença for grande, aparece como rubber banding. - **Compensação de lag** (Lag compensation): Técnica em que o servidor, ao decidir um ataque, volta no tempo até o momento que o atacante via na tela para checar se o golpe acertou. Para não ser injusto com quem leva o golpe, há um limite para o quanto se volta. Em shooters competitivos, uns 0,2–0,25 s é comum, e há casos que voltam até 1 s, como o padrão da Source Engine. - **Servidor autoritativo** (Authoritative server): Design em que só o servidor dá a palavra final. Isso impede trapaças, mas todo resultado depende de uma ida e volta ao servidor. Por isso a espera é disfarçada com predição e feedback no cliente. - **Lockstep** (Deterministic lockstep): Modelo em que todos trocam apenas os comandos e calculam exatamente a mesma coisa no mesmo turno. Os comandos recebem um atraso fixo, e se o comando de um jogador atrasa, todos esperam. - **Buffer de input no servidor** (Server-side input buffer): Buffer em que o servidor acumula alguns comandos de cada jogador e consome um por tick. Assim, mesmo quem tem jitter alto aparece com movimento suave para os outros, mas as ações dessa pessoa são confirmadas no servidor com esse atraso a mais. - **Listen server** (Listen server): Modelo em que o PC de um dos jogadores roda o jogo e também faz o papel de servidor. O host tem ping 0, mas se a conexão ou o PC dele for lento, todos sofrem com lag. - **Phasing** (Phasing): Recurso que, no mesmo lugar, mostra NPCs e terrenos diferentes conforme o progresso nas quests. Se dois personagens estão em etapas diferentes, é normal o NPC aparecer para um e não para o outro. - **Netcode de rollback** (Rollback netcode (GGPO)): Modelo que prevê os comandos do adversário e segue em frente; se o comando real for diferente, volta aos frames anteriores e recalcula. Muito usado em jogos de luta. É um conceito diferente do rollback de banco de dados. - **Buffer de comandos** (Input buffer, spell queue): Guardar o próximo comando apertado pouco antes de um cooldown ou de uma animação terminar e executá-lo no instante em que termina. Evita que o tempo de ida e volta entre no meio de um combo. - **Feedback no cliente** (Client-side feedback): Tocar animações, sons e efeitos antes da confirmação do servidor. Só os resultados que precisam ser confirmados, como dano e recompensas, esperam a resposta do servidor. Se o servidor recusar, o que foi mostrado precisa ser desfeito. - **TCP** (Transmission Control Protocol): Protocolo que entrega os dados em ordem e sem faltar nada. Até receber de novo um pacote perdido, não entrega ao jogo os pacotes que vêm depois. - **UDP** (User Datagram Protocol): Protocolo que entrega o que for enviado, sem nenhuma garantia. Não há espera, mas o próprio jogo precisa tratar as perdas e a ordem. - **UDP confiável** (Reliable UDP (KCP, ENet…)): Abordagem que implementa sobre o UDP apenas a retransmissão e a entrega em ordem que forem necessárias. - **HOL blocking** (Head-of-line blocking): Quando o primeiro item da fila fica bloqueado e todos os que vêm atrás ficam esperando. É a causa do avanço rápido no TCP. - **RTO** (Retransmission timeout): Timer de retransmissão. Tempo que o TCP espera antes de considerar um pacote perdido e reenviá-lo. No Linux é ping + 200 ms ou mais, e dobra a cada falha. - **Algoritmo de Nagle** (Nagle’s algorithm): Recurso do TCP que junta dados pequenos até chegar a confirmação (ACK) dos dados enviados antes e manda tudo de uma vez, para economizar pacotes. Em jogos, em geral precisa ser desligado. - **TCP_NODELAY** (TCP_NODELAY): Opção de socket que desliga o algoritmo de Nagle. Mensagens pequenas saem na hora. - **ACK atrasado** (Delayed ACK): Recurso que envia a confirmação de recebimento um pouco depois, junto com outros dados. No Linux, normalmente 40 ms (máximo de 200 ms); no Windows, as versões antigas usavam 200 ms e as atuais usam 40 ms. - **Buffer de socket** (SO_SNDBUF / SO_RCVBUF): Tamanho do espaço de espera para envio e recepção que o SO mantém para cada socket. Pequeno demais, transborda; grande demais, acumula dados velhos que ficam esperando. - **keepalive** (SO_KEEPALIVE): Recurso do TCP que verifica se uma conexão ociosa continua viva. Vem desligado por padrão e, mesmo ligado, o padrão só faz a verificação depois de 2 horas. - **RST** (TCP reset): Sinal do TCP que encerra a conexão à força, na hora. Os dados que ainda não foram enviados são descartados. - **Heartbeat** (Heartbeat): Sinal de “estou vivo” que o próprio jogo envia periodicamente. Serve para detectar conexões mortas e manter a conexão ativa nos equipamentos do caminho. - **Timeout** (Timeout): Tempo sem resposta a partir do qual se considera que houve falha. Curto demais gera falsos alarmes; longo demais atrasa a detecção. - **NAT** (Network Address Translation): Recurso do roteador que faz vários dispositivos da casa saírem para a internet por um único IP público, registrando cada conexão na tabela NAT. - **CGNAT** (Carrier-grade NAT): NAT em grande escala com que a operadora divide um mesmo IP entre vários assinantes. - **MTU** (Maximum Transmission Unit): Tamanho máximo de um pacote enviado de uma vez. Normalmente 1.500 bytes, e menor em trechos com VPN ou PPPoE. - **Bufferbloat** (Bufferbloat): Quando um equipamento acumula filas grandes demais e a latência sobe para centenas de ms. - **SQM** (Smart Queue Management (fq_codel, CAKE)): Recurso do roteador que mantém as filas curtas e envia cada fluxo de forma justa. É a solução para o bufferbloat. - **QoS** (Quality of Service): Recurso que dá prioridade ao tráfego importante para que ele saia primeiro. - **Peering** (Peering): Ponto em que as operadoras interligam suas redes. Costuma ficar congestionado à noite. - **BGP** (Border Gateway Protocol): Protocolo com que as operadoras informam umas às outras por qual rota enviar o tráfego na internet. Quando os anúncios mudam, a rota e o ping mudam. - **DDoS** (Distributed Denial of Service): Ataque que envia um volume enorme de tráfego de muitas origens para derrubar um serviço. - **Centro de scrubbing** (DDoS scrubbing center): Ponto de presença (PoP) de um serviço de proteção contra DDoS que, durante um ataque, recebe primeiro o tráfego destinado ao servidor, filtra o ataque e repassa só o tráfego legítimo. Se ele fica longe, a rota fica mais longa. - **Firewall** (Firewall): Equipamento ou programa que só deixa passar conexões permitidas. Rastreia as conexões em uma tabela de sessões. - **Load balancer** (Load balancer): Equipamento que distribui as conexões que chegam entre vários servidores. - **Tabela de sessões** (Session table, conntrack): Tabela em que o equipamento ou o SO rastreia as conexões atuais. O tamanho dela é limitado. - **Microburst** (Microburst): Quando a média é baixa, mas o tráfego se concentra em instantes curtíssimos, de 1 ms ou menos. - **NIC** (Network Interface Card): A placa de rede do servidor. - **Ring buffer** (Ring buffer): Buffer que guarda os pacotes recebidos pela NIC até a CPU retirá-los. Reaproveita em ciclo um número fixo de slots; quando todos estão ocupados, os pacotes novos são descartados. - **Interrupção** (Interrupt): Sinal com que um dispositivo avisa a CPU de que “tem trabalho”. - **RSS** (Receive Side Scaling): Recurso da NIC que distribui os pacotes recebidos entre várias filas de recepção para que vários núcleos de CPU os processem. - **PPS** (Packets per second): Pacotes por segundo. Servidores de jogos costumam bater no limite desse número antes do limite de largura de banda. - **Kernel** (Kernel): O núcleo do sistema operacional. Cuida da rede, da memória e da distribuição de CPU. - **backlog** (Listen backlog): Fila em que esperam os novos pedidos de conexão que o servidor ainda não aceitou. Quando a fila enche, o Linux descarta os pedidos novos em silêncio, e o Windows responde com uma recusa. - **TIME_WAIT** (TIME_WAIT): Estado em que o lado que fechou a conexão primeiro mantém aquela combinação de portas por um tempo (60 s no Linux), para o caso de chegarem pacotes atrasados. - **CPU steal** (Steal time): Tempo que uma máquina virtual esperou por CPU porque o servidor físico estava entregando a CPU a outras máquinas virtuais. Aparece no valor st do top. - **Throttling de CPU** (CFS throttling): Pausa forçada de um contêiner até o período seguinte quando ele gasta toda a cota de CPU (quota) dentro do período definido (CFS period, normalmente 100 ms). - **Descritor de arquivo** (File descriptor): Número (fd) atribuído a cada arquivo ou conexão que um processo abre. A quantidade é limitada. - **Thread** (Thread): Unidade de trabalho que roda de forma independente dentro de um programa. Várias threads podem rodar ao mesmo tempo. - **Troca de contexto** (Context switch): Quando a CPU troca a thread em execução por outra. Tem custo. - **Lock** (Lock, Mutex): Mecanismo que garante que só uma thread por vez use dados compartilhados. - **Deadlock** (Deadlock): Estado em que threads ficam paradas para sempre, cada uma esperando o lock que a outra segura. - **Pool de threads** (Thread pool): Conjunto de worker threads criadas de antemão. Quando todas estão ocupadas, as tarefas novas esperam. - **I/O assíncrono** (epoll, IOCP, io_uring): Modelo em que o programa não fica parado esperando a entrada e saída: faz outras coisas e recebe um aviso quando a operação termina. - **AOI** (Area of Interest): O “alcance de visão” de cada jogador. Só as mudanças dentro dele são enviadas, o que reduz o tráfego. Para baratear o cálculo de quem está dentro do alcance, o mapa normalmente é dividido em uma grade (grid) e só as células próximas são verificadas. - **Broadcast** (Broadcast, fan-out): Enviar uma mudança a todos os jogadores que podem vê-la. Se todos num grupo enxergam uns aos outros, o volume a enviar cresce com o quadrado do número de jogadores. - **GC** (Garbage collection): Recurso que recupera automaticamente a memória que não está mais em uso. Durante o GC, o programa às vezes para. - **Heap** (Heap): Área de memória que o programa aloca sob demanda enquanto roda. - **Vazamento de memória** (Memory leak): Bug em que a memória já usada não é devolvida e o consumo só cresce. Acontece mesmo com GC, se algum ponto do código continua referenciando objetos que já não servem. - **Swap** (Swap, paging): Mover parte da memória para o disco quando falta RAM. Voltar a usar essa memória movida é mais de 1.000 vezes mais lento que usar a RAM. - **OOM killer** (Out-of-memory killer): Recurso do Linux que, quando a memória acaba, escolhe o processo que mais usa memória e o encerra à força. Em contêineres, basta atingir o limite de memória para ele agir. - **Cache miss** (Cache miss): Quando o dado não está no cache próximo da CPU e é preciso buscá-lo na memória, que é mais lenta. - **IOPS** (I/O operations per second): Número de leituras e escritas que o disco consegue processar por segundo. Em discos na nuvem, o limite depende de quanto você paga. - **fsync** (fsync): Comando que espera até os dados estarem de fato gravados no disco. Uma escrita normal vai primeiro para a memória do SO e só depois para o disco; se o servidor desligar nesse meio-tempo, os dados podem se perder. O fsync é seguro, mas lento. - **Créditos de burst** (Burst credits): Saldo acumulado que permite a discos e servidores na nuvem passarem, por pouco tempo, do desempenho base. Quando o saldo zera, o desempenho cai para a base. - **Índice** (Index): Estrutura de busca do banco de dados. Sem ela, é preciso ler a tabela inteira. - **Full scan** (Full table scan): Consulta que verifica todas as linhas da tabela sem usar índice. - **Plano de execução** (Query plan): Como o banco decide resolver uma query: em que ordem e com quais índices. Mesmo sem mudança no código, se o banco trocar o plano, a mesma query pode ficar lenta de repente. - **Transação** (Transaction): Conjunto de operações no banco que acontece no esquema “tudo ou nada”. Trocas entre jogadores sempre devem ser feitas em uma transação. Como as linhas alteradas ficam com lock até o fim, quanto mais curta, melhor. - **Pool de conexões** (Connection pool): Conjunto de conexões com o banco abertas de antemão. Quando todas estão em uso, os pedidos novos esperam. - **Hot row** (Hot row): Uma única linha que muitos pedidos tentam alterar ao mesmo tempo. Causa contenção de lock. - **Atraso de replicação** (Replication lag): Quanto tempo a réplica do banco está atrás do BD primário, sem conseguir acompanhá-lo. - **Rollback** (Rollback): Quando uma gravação é cancelada e tudo volta ao estado anterior. O jogador sente que “o item sumiu”. - **Cache** (Cache (Redis etc.)): Cópia de dados usados com frequência em um lugar mais rápido. Reduz a carga no banco de dados. - **Checkpoint** (Checkpoint): Gravação periódica no disco, de uma vez, das alterações que o banco acumulou na memória. Nesse momento, gravações e consultas podem ficar lentas por um instante. - **Failover** (Failover): Passagem para o servidor ou o BD reserva quando o principal cai. Durante a troca, não dá para gravar por um instante, e se a replicação estava atrasada, os últimos dados podem se perder. - **MVCC** (Multi-version concurrency control): Modelo em que o banco guarda versões antigas por um tempo para que quem lê e quem altera não bloqueiem um ao outro. Se houver uma transação aberta há muito tempo, as versões antigas se acumulam e o banco fica lento. - **Cache stampede** (Cache stampede): Quando o cache se esvazia de uma vez e todos os pedidos vão para a origem (o banco de dados). - **Gateway** (Gateway): Servidor intermediário que recebe as conexões dos clientes e as repassa aos servidores do jogo que ficam atrás dele. - **Circuit breaker** (Circuit breaker): Mecanismo que corta por um tempo as chamadas a um serviço que continua falhando e já as trata como falha, para evitar falhas em cascata. Depois de um tempo, faz uma ou duas chamadas de teste e, se o serviço voltou, libera as chamadas de novo. - **Falha em cascata** (Cascading failure): Quando a falha de um ponto se espalha para outros serviços pela cadeia de chamadas. - **Autoscaling** (Autoscaling): Recurso que aumenta e reduz automaticamente o número de servidores conforme a carga. Subir novos servidores leva tempo. - **Watchdog** (Watchdog): Timer que vigia se o servidor parou. Se o game loop fica parado além de um tempo definido (de alguns a dezenas de segundos), ele grava o estado (dump) e encerra o servidor à força para que seja reiniciado. - **Utilização** (Utilization): Fração do tempo em que os workers (o que processa os pedidos, como núcleos de CPU, threads e conexões do banco) estão ocupados. Acima de 80–90%, a espera cresce muito rápido. - **p99** (99th percentile): Valor em que 99 de cada 100 medições são mais rápidas e cerca de 1 é mais lenta. Mostra o lag que os jogadores sentem melhor que a média. - **V-Sync** (Vertical sync): Recurso que envia os frames no ritmo de atualização da tela. Elimina o tearing, mas causa input lag, e se o FPS cai abaixo da taxa de atualização, pode alternar entre 60 e 30 e gerar engasgos. - **Taxa de atualização variável** (VRR, G-Sync, FreeSync): Recurso em que o monitor atualiza a imagem no momento em que o frame fica pronto. Reduz os engasgos e o input lag causados pela alternância entre 60 e 30 do V-Sync. - **Anti-cheat** (Anti-cheat): Módulo de segurança que bloqueia hacks. Quando uma verificação periódica ou o heartbeat com o servidor falha, pode causar engasgos ou desconexão. - **Overlay** (Overlay): Recurso de mensageiros, gravadores e contadores de FPS que desenha por cima da tela do jogo. Como interfere no processo de desenho do jogo, pode causar engasgos. - **Compilação de shaders** (Shader compilation): Conversão dos programas de efeitos gráficos para a GPU. Se não for feita antes, a imagem dá um engasgo na primeira vez que o efeito aparece; ao atualizar o driver de vídeo, o resultado salvo é invalidado e a compilação é refeita. - **Thread principal** (Main thread, Game thread): Thread central do jogo, que processa em sequência as regras do jogo e a preparação da tela. Se qualquer tarefa demorar ali, a tela para durante esse tempo. - **Resolução do timer** (Timer resolution): Menor intervalo com que o sistema operacional consegue acordar um programa que está dormindo. No Windows, o padrão é 15,6 ms; se o programa não mudar isso, até um “me acorde em 1 ms” acorda atrasado. - **Thermal throttling** (Thermal throttling): Proteção que reduz sozinha a velocidade da CPU e da GPU quando o aparelho esquenta. Em celulares, é comum depois de alguns minutos a algumas dezenas de minutos de jogo. - **VRAM** (Video memory): Memória dedicada da placa de vídeo. As texturas e os modelos ficam ali para serem desenhados. Se ela faltar, os dados vão e voltam da memória do PC por um caminho lento e a imagem engasga. - **Net graph** (Net graph): Indicador de desenvolvimento e depuração que mostra na tela do jogo gráficos em tempo real de ping, perda, FPS e tick. Se ele aparecer no vídeo enviado para reportar o lag, fica muito mais fácil achar a causa. - **Taxa de retransmissão** (Retransmission rate): Fração dos pacotes TCP enviados que precisou ser reenviada. Não existe um padrão oficial, mas uma média do servidor inteiro abaixo de 0,1% costuma ser saudável, e acima de 1% muitos jogadores tendem a sentir lag. Veja também quantas vezes o valor subiu em relação ao normal. - **SACK** (Selective ACK): Recurso do TCP em que o receptor informa em detalhe “recebi este trecho e só falta esta parte”. Mesmo perdendo vários pacotes, dá para recuperar tudo de uma vez. - **RACK-TLP** (Recent ACK, Tail Loss Probe): Recurso do TCP que detecta perdas com base no tempo e, se fica um tempo sem ACK, reenvia o último pacote para adiantar a recuperação. É o padrão no Linux e no Android recentes. No Windows, TLP e RACK são padrão a partir do Windows 10 (1607) e do Server 2016, e o RACK novo, que recupera até retransmissões perdidas, só a partir do Server 2022. Só funciona em conexões com SACK ativado. - **Retransmissão espúria** (Spurious retransmission): Reenvio de um pacote que não se perdeu: ele só chegou atrasado ou fora de ordem e foi tomado como perdido. Desperdiça banda e reduz a taxa de envio sem necessidade. - **Janela zero** (Zero window): Estado em que o buffer do receptor encheu e ele avisa “pare de enviar um pouco”. Parece retransmissão, mas a conexão está normal: o programa do lado receptor é que não leu os dados a tempo. - **thin stream** (Thin stream): Conexão que envia pacotes pequenos e espaçados, como a de um jogo. Como os sinais para o fast retransmit demoram a se acumular, uma perda causa uma parada longa. - **Policer** (Policer): Limitação de velocidade que descarta na hora os pacotes acima da taxa definida, sem colocá-los em fila. O método que coloca os pacotes em fila e os libera devagar se chama shaper. - **Pacing** (Pacing): Distribuir o envio dos pacotes ao longo do tempo, sem mandar tudo de uma vez. Evita que buffers pequenos transbordem. - **ECN** (Explicit Congestion Notification): Recurso que, durante um congestionamento, marca os pacotes como “congestionado” sem descartá-los, para que o emissor reduza a velocidade. Assim o congestionamento é sinalizado sem perda. Só funciona se as duas pontas e os equipamentos do trecho congestionado tiverem suporte. - **MSS** (Maximum Segment Size): Tamanho máximo dos dados que o TCP coloca em um pacote. Normalmente 1.460 bytes; reduzi-lo para caber em trechos com túnel evita o black hole de MTU. - **Handover** (Handover): Quando um celular em movimento troca a antena (estação rádio base) à qual está conectado. - **Percentil** (Percentile (p50, p95, p99)): Valor que fica em uma certa posição percentual quando os valores são ordenados do menor para o maior. O p50 é a mediana; o p99 fica perto da medição mais lenta de cada 100. Mostra os picos que a média esconde. - **Latência de cauda** (Tail latency): Latências longas que aparecem de vez em quando, enquanto a maioria das respostas é rápida. Quase não aparecem na média, mas é disso que os jogadores lembram como lag. - **Monitoramento sintético** (Synthetic monitoring): Medição da qualidade da rota feita por dispositivos ou servidores de medição, que enviam periodicamente ping, traceroute etc. a partir de pontos definidos, sem depender de jogadores reais. O RIPE Atlas é a ferramenta pública mais conhecida. - **Intervalo de agregação** (Aggregation interval): Quantos segundos ou minutos de valores um ponto do gráfico resume. Quanto maior o intervalo, mais os picos curtos se diluem na média. - **Postmortem** (Postmortem): Documento escrito depois de um incidente com o que aconteceu, por que aconteceu e o que vai mudar. O objetivo é evitar que se repita, sem procurar culpados. - **C-state** (CPU idle state): Estado de economia de energia em que a CPU entra quando está ociosa. Quanto mais profundo, mais energia economiza, mas mais tempo leva para despertar. - **Live migration** (Live migration): Quando a nuvem move uma máquina virtual em execução para outro host, por exemplo para a manutenção do host. No momento da mudança, ela pode parar por um instante. - **SNAT** (Source NAT): NAT que troca o endereço de origem dos pacotes de saída por um endereço público. O número de portas que um endereço público pode usar é limitado, e quando elas acabam, as conexões novas falham. - **Gateway NAT** (NAT gateway): Recurso da nuvem que permite aos servidores de uma rede privada compartilhar um único endereço público para sair para a internet. Há limite de conexões simultâneas por destino. - **Internet via satélite de órbita baixa** (LEO satellite internet): Internet fornecida por satélites a altitudes de centenas a milhares de km. A latência é bem menor que a dos satélites geoestacionários, mas pode dar picos quando o satélite conectado muda. - **GeoIP** (IP geolocation): Banco de dados que estima o país, a cidade e a operadora a partir do endereço IP. Tem entradas erradas ou desatualizadas, o que às vezes faz o jogador ser direcionado a um servidor distante. - **Certificado TLS** (TLS certificate): Documento digital que prova que o servidor é mesmo quem diz ser. Tem prazo de validade; quando expira, a conexão criptografada falha e não é possível conectar. - **Geração de frames** (Frame generation): Tecnologia em que a placa de vídeo insere frames previstos entre os frames realmente renderizados para aumentar o FPS. A imagem fica mais suave, mas a latência entre o comando e a tela pode aumentar.