- Xeon novo, mais lento que o antigo: um bug no cpuidle “menu” fazia Sapphire Rapids registrar 151 µs de latência média em rede, contra 12 µs no Ice Lake (até 12x pior).
- O vilão era o “sono profundo” na hora errada: com NOHZ_FULL, o governor trocava previsões curtas por next_timer_ns (muitas vezes 10 ms+) e acabava escolhendo PC6, custoso para “acordar” em plataformas modernas.
- Patch simples, efeito gigante: ao adicionar 25% de margem e limitar pela próxima expiração, a latência em Sapphire Rapids caiu para ~30 µs (melhora de ~5x) sem regressões perceptíveis em Ice Lake/Skylake.
O que deveria ser uma vitória para data centers virou uma ironia difícil de engolir: plataformas Intel de servidor recentes, como Sapphire Rapids, passaram a exibir uma latência de “acordar e responder” tão alta que, em workloads sensíveis a rede, ficam na prática até 12 vezes piores do que uma geração anterior. Não é exagero de benchmark, é um comportamento observado com o governor “menu” do cpuidle, em cenários com NOHZ_FULL, onde cada microssegundo vira dinheiro, ou estabilidade, ou vantagem competitiva.
Os números chamam atenção. Em medições com qperf tcp_lat, Sapphire Rapids aparece com cerca de 151 µs de latência média, contra 12 µs em Ice Lake e 21 µs em Skylake. Em aplicações como HPC, tempo real e trading, isso não é “só um pouco pior”, é um tipo de regressão que muda o desenho do sistema.
O patch que devolve a velocidade aos seus servidores modernos
O problema está na forma como o governor “menu” prevê o tempo ocioso. Quando o tick já está parado e a previsão de idle fica abaixo de 2 ms, o algoritmo troca a estimativa e passa a usar next_timer_ns diretamente. Na prática, isso frequentemente significa olhar para um timer distante (10 ms ou mais) e concluir: “dá para dormir fundo”.
Só que aí entra a pegadinha das CPUs modernas de servidor. Em plataformas a partir de 2022, o custo de sair de estados profundos, como o pacote PC6, pode crescer bastante por mudanças arquiteturais e de energia: arquitetura em tiles com power gating por bloco, DDR5 com seu próprio gerenciamento, restauração de links (como CXL), além de uma malha interna mais complexa para ressincronizar. O resultado é que, quando um pacote de rede chega 500 µs depois, a CPU ainda está pagando a conta do “acordei do sono errado”.
Pensa como uma casa inteligente mal configurada: você vai piscar os olhos e o sistema apaga as luzes da casa inteira, tranca portas, baixa persianas, entra em modo economia extrema. Aí alguém toca a campainha e, até a casa “voltar ao normal”, você já perdeu o timing.
A correção proposta por Ionut Nechita é simples e, justamente por isso, brutalmente eficaz. Em vez de substituir a previsão curta por um timer longo, o patch adiciona uma margem de segurança de 25% na previsão quando o tick está parado e só então limita esse valor ao next_timer_ns:
- sai de “100% timer-based” para uma previsão mais conservadora,
- evita escolher estados profundos demais por causa de um timer distante,
- não usa thresholds fixos por plataforma e não depende de tuning específico para um Xeon ou outro.
Na prática, o patch troca a armadilha por um freio inteligente: se a previsão era 500 µs e o próximo timer está em 10 ms, a previsão vira 625 µs (500 µs + 25%) e não 10 ms. Isso tende a manter o sistema em estados mais adequados para latência, reduzindo o tempo de resposta quando chega tráfego.
O impacto nos resultados é o tipo de “milagre” que só parece milagre porque era um bug muito caro. Em Sapphire Rapids, a latência média cai de 151 µs para ~30 µs, uma melhora de cerca de 5x. Em Ice Lake e Skylake, não aparece regressão relevante (12 µs continua 12 µs, 21 µs continua 21 µs). E, segundo o relato do autor, a diferença de consumo em workloads mistos fica abaixo de 1%, dentro do ruído de medição.
Se você administra infraestrutura sensível à latência, vale a pena olhar para duas coisas agora: o cenário em que o NOHZ_FULL está habilitado e a sua árvore de kernel (porque esse tipo de fix costuma seguir para o mainline quando ganha consenso na lista). A recomendação prática é direta: acompanhe as atualizações do kernel e, quando a correção entrar, priorize a adoção nos nós onde rede e tail latency importam mais do que “economizar o último watt”.
