5 pontos por GN⁺ 2024-07-29 | 1 comentários | Compartilhar no WhatsApp
  • O ajuste de desempenho de rede no Linux consiste em interpretar, com base nos gargalos, o fluxo pelo qual os pacotes passam por buffer em anel da NIC, IRQ, NAPI, softIRQ, qdisc e buffers TCP até chegar ao socket da aplicação
  • No caminho de recepção, a NIC grava os pacotes na RAM via DMA e gera uma HardIRQ; o driver agenda a NAPI para esvaziar o buffer em anel em NET_RX_SOFTIRQ e depois encaminha os dados para as camadas IP/TCP e para o buffer de recepção do socket
  • ethtool, /proc/net/softnet_stat, ss, netstat e sysctl são o ponto de partida para observação e ajuste, e os principais eixos são coalescência de interrupções, afinidade de IRQ, RSS/RPS/RFS/aRFS, netdev_budget, netdev_max_backlog, txqueuelen e buffers TCP de leitura/escrita
  • Não existe uma configuração única que funcione para todos os sistemas; aumentar o buffer em anel pode reduzir drops, mas aumentar a latência, e a coalescência de interrupções pode reduzir o uso de CPU e HardIRQs em troca de custo de latência
  • O processamento de pacotes de alto desempenho pode ser ampliado com opções como PACKET_MMAP, DPDK, PF_RING e XDP/AF_XDP, mas dependência de hardware, uso de CPU e requisitos de versão do kernel variam entre bypass do kernel, zero-copy e caminhos rápidos dentro do kernel

Caminho de recepção no Linux: da NIC ao socket

  • O dispositivo de rede gera uma IRQ para sinalizar a chegada de pacotes, e o mapeamento de IRQ no Linux fica armazenado em /proc/interrupts
  • O manipulador de IRQ é executado com prioridade muito alta e pode bloquear a geração de IRQs adicionais, por isso o driver adia trabalhos longos para fora do contexto de IRQ
  • Para esse processamento adiado, usa-se softIRQ; no processamento de recepção de rede, são criados por CPU a thread de kernel ksoftirqd/<cpu-number>, softnet_data e poll_list
  • net_dev_init registra NET_RX_SOFTIRQ no sistema de softIRQ, e o respectivo handler é net_rx_action
  • Chegada do pacote e processamento da NAPI

    • A NIC grava na RAM, via DMA, os dados recebidos da rede no buffer em anel
    • Algumas NICs são NICs multiqueue, com vários buffers em anel
    • Quando a NIC gera uma HardIRQ, o handler de IRQ do driver é executado
    • O driver limpa a IRQ da NIC e chama napi_schedule para iniciar o loop de polling da softIRQ da NAPI
    • napi_schedule adiciona a estrutura de poll NAPI do driver à poll_list da CPU atual e define o bit pendente de softIRQ
    • Quando ksoftirqd chama __do_softirq, é executado net_rx_action, o handler de NET_RX_SOFTIRQ que estava pendente
  • GRO e entrada na pilha de protocolos

    • net_rx_action verifica a lista de poll da NAPI e inspeciona o budget e o tempo decorrido para evitar que a softIRQ monopolize a CPU
    • A função poll do driver coleta os pacotes do buffer em anel na RAM
    • Os pacotes são entregues a napi_gro_receive
    • GRO (Generic Receive Offloading) é uma técnica de offloading baseada em software que recompõe pacotes pequenos em pacotes maiores, reduzindo a quantidade de pacotes que a aplicação precisa processar
    • Se o GRO não retiver o pacote, ele sobe pela pilha de protocolos via netif_receive_skb
  • Ramificação conforme a ativação do RPS

    • Quando o RPS está desativado:
      • netif_receive_skb entrega os dados a __netif_receive_core
      • __netif_receive_core entrega os dados a taps e handlers registrados da camada de protocolo
    • Quando o RPS está ativado:
      • netif_receive_skb entrega os dados a enqueue_to_backlog
      • O pacote entra na fila de entrada por CPU
      • A estrutura NAPI da CPU remota é adicionada à poll_list daquela CPU, e uma IPI é enfileirada para acordar a thread de softIRQ da CPU remota
      • O ksoftirqd da CPU remota coleta os pacotes da fila de entrada da CPU com a função de poll process_backlog
  • IP, TCP e buffer de recepção do socket

    • Os pacotes são recebidos na camada IPv4 por ip_rcv e passam por netfilter e otimizações de roteamento
    • Os dados destinados ao sistema atual são entregues às camadas de protocolo superiores, como UDP ou TCP
    • No caminho de recepção do TCP, eles passam por tcp_v4_rcv, pela máquina de estados finitos do TCP, pela busca do socket e entram no buffer de recepção
    • O tamanho do buffer de recepção segue as regras de tcp_rmem
    • Se tcp_moderate_rcvbuf estiver ativado, o kernel ajusta automaticamente o buffer de recepção
    • tcp_rmem contém os valores mínimo, padrão e máximo do buffer de recepção de sockets TCP
    • Usar SO_RCVBUF desativa o ajuste automático do buffer de recepção para aquele socket
    • net.core.rmem_max é o limite superior do tamanho do buffer de recepção TCP, e uma janela maior permite enviar mais dados antes do envio de ACK, reduzindo a latência e aumentando a vazão

Caminho de transmissão no Linux: da aplicação à NIC

  • O caminho de transmissão é mais simples que o de recepção, mas envolve qdisc, buffer de escrita TCP, DMA e IRQ
  • Quando a aplicação envia uma mensagem com uma chamada como sendmsg, o caminho de transmissão TCP aloca um skb_buff
  • O pacote entra no buffer de escrita do socket, de tamanho tcp_wmem
    • tcp_wmem contém os valores mínimo, padrão e máximo do buffer de transmissão de sockets TCP
    • O kernel ajusta dinamicamente o tamanho do buffer de transmissão TCP entre os valores mínimo e máximo
    • Usar SO_SNDBUF desativa o ajuste automático do buffer de transmissão para aquele socket
    • net.core.wmem_max é o limite superior do tamanho do buffer de transmissão TCP
  • O cabeçalho TCP e o cabeçalho IP são criados e, após passar por LOCAL_OUT, roteamento, POST_ROUTING e fragmentação, dev_queue_xmit chama a função de transmissão L2
  • A qdisc de saída usa o comprimento txqueuelen e o algoritmo default_qdisc
  • O driver coloca o pacote no buffer em anel TX e executa NET_TX_SOFTIRQ após o timeout tx-usecs ou após tx-frames
  • A NIC busca o pacote na RAM via DMA e o transmite; após a conclusão da transmissão, gera uma HardIRQ
  • O driver processa essa IRQ e agenda o sistema de poll da NAPI para liberar a RAM

Ferramentas de observação e pontos básicos de verificação

  • /proc/net/softnet_stat

    • Cada linha de /proc/net/softnet_stat representa um núcleo de CPU, começando pela CPU0
    • As estatísticas de cada coluna são fornecidas em hexadecimal
    • A 1ª coluna é o número de frames recebidos pelo manipulador de interrupção
    • A 2ª coluna é o número de frames descartados por exceder netdev_max_backlog
    • A 3ª coluna é o número de vezes em que o ksoftirqd esgotou netdev_budget ou o tempo de CPU enquanto ainda havia trabalho pendente para processar
    • As demais colunas podem variar conforme a versão do Linux
  • /proc/net/sockstat e ss

    • Em /proc/net/sockstat, verifique o campo mem
    • Esse valor é calculado somando o sk_buff->truesize de todos os sockets
    • ss é uma ferramenta para despejar estatísticas de sockets e pode exibir informações semelhantes ao netstat, além de mais detalhes sobre TCP e estados
    • ss -tm é usado para verificar o uso de memória de sockets TCP
    • rmem_alloc: memória alocada para pacotes recebidos
    • rcv_buf: memória total que pode ser alocada para pacotes recebidos
    • wmem_alloc: memória usada por pacotes enviados que já foram entregues à camada 3
    • snd_buf: memória total que pode ser alocada para pacotes enviados
    • wmem_queued: memória alocada para pacotes enviados que ainda não foram entregues à camada 3
    • sock_drop: número de pacotes descartados antes de serem demultiplexados para um socket
  • netstat e sysctl

    • netstat é uma ferramenta de linha de comando que exibe conexões de rede abertas e estatísticas da pilha de protocolos, obtendo informações do sistema de arquivos /proc/net/
    • /proc/net/dev: informações do dispositivo
    • /proc/net/tcp: informações de sockets TCP
    • /proc/net/unix: informações de Unix domain sockets
    • sysctl é um comando para alterar configurações de sistema e rede em vez de gravar valores diretamente no sistema de arquivos /proc
    • sysctl -w variable=value é usado para mudanças temporárias, e mudanças permanentes são aplicadas editando /etc/sysctl.conf e depois executando sysctl -p

Buffer de anel da NIC e ajuste de interrupções

  • Buffer de anel da NIC

    • O buffer de anel RX é um buffer circular FIFO de tamanho fixo localizado na RAM
    • O próprio buffer de anel não armazena os dados dos pacotes; ele armazena descritores que apontam para o skb colocado na RAM via DMA
    • Se houver descartes ou overruns, é possível aumentar o tamanho da fila, mas isso pode aumentar a latência como efeito colateral
    • Em muitos casos, apenas aumentar o tamanho do buffer de recepção já pode evitar perda de pacotes, dando ao kernel um pouco mais de tempo para esvaziar o buffer
    • A verificação e a alteração são feitas com ethtool
    • ethtool -g eth3: verifica os tamanhos atuais do anel RX/TX e os valores máximos
    • ethtool -G eth3 rx 8192 tx 8192: aumenta os buffers RX/TX até o valor máximo
    • Monitore com ethtool -S eth3 e contadores como err, drop, over, miss, timeout, reset, collis
  • Coalescência de interrupções em hardware

    • A NIC pode acumular referências de pacotes no buffer de anel RX até que a condição de timeout rx-usecs ou rx-frames seja atingida e então gerar uma HardIRQ; isso é chamado de Interrupt coalescence
    • Interromper cedo demais faz o kernel interromper com frequência o trabalho em execução, o que piora o desempenho do sistema
    • Interromper tarde demais pode impedir que o tráfego seja drenado da NIC rápido o suficiente, causando sobrescrita e perda de tráfego
    • Ajustar a coalescência de interrupções pode reduzir o uso de CPU e HardIRQ e aumentar o throughput, mas pode ter custo de latência
    • É possível verificar os parâmetros de coalescência com ethtool -c eth3 e alterá-los com algo como ethtool -C eth3 adaptive-rx off rx-usecs 0 rx-frames 0
    • No modo adaptativo, a placa estima dinamicamente as configurações de coalescência observando o padrão de tráfego e o padrão de recepção do kernel

Afinidade de IRQ e balanceamento de carga entre CPUs

  • Afinidade de IRQ

    • As IRQs têm um atributo smp_affinity que define quais núcleos de CPU podem executar a ISR daquela IRQ
    • Alinhar a afinidade da interrupção e a afinidade das threads da aplicação a núcleos específicos de CPU pode melhorar o desempenho da aplicação por compartilhamento de cache line
    • Por padrão, isso é controlado pelo daemon irqbalance
    • Antes de fazer ajuste manual, é preciso parar o irqbalance
    • /proc/irq/<IRQ_NUMBER>/smp_affinity armazena uma bitmask hexadecimal que representa os núcleos de CPU
    • Em um servidor com 4 núcleos, o valor padrão f significa que a IRQ pode ser tratada por qualquer CPU
    • echo 1 > /proc/irq/32/smp_affinity faz com que apenas a CPU0 seja usada
    • Em sistemas com mais de 32 núcleos, grupos de 32 bits são separados por vírgula
    • A afinidade de IRQ pode melhorar o desempenho apenas em configurações muito específicas e workloads predefinidos, e pode ser uma faca de dois gumes
  • RSS

    • Em NICs rápidas, se os pacotes forem recebidos por uma única fila e uma única CPU, um núcleo pode acabar assumindo toda a responsabilidade pelo processamento dos dados enquanto os outros ficam ociosos
    • RSS (Receive-side scaling) é uma tecnologia de NIC que distribui o tráfego entre várias filas de envio e recepção
    • A NIC calcula um hash com base em IP de origem/destino e porta TCP/UDP de origem/destino, atribui os pacotes do mesmo fluxo a uma única fila e distribui os fluxos de forma equilibrada entre as filas
    • O RSS oferece os benefícios do processamento de recepção em paralelo em ambientes multiprocessados
    • Segundo a documentação do kernel Linux, o RSS deve ser ativado quando a latência for importante ou quando o processamento de interrupções de recepção for um gargalo; em redes de baixa latência, o ideal é configurar uma fila para cada CPU do sistema
  • RPS, RFS, aRFS

    • RPS (Receive Packet Steering) é próximo de uma implementação em software do RSS
    • Enquanto o RSS escolhe a fila e a CPU que executarão o manipulador de interrupção de hardware, o RPS escolhe a CPU que fará o processamento de protocolo acima do manipulador de interrupção
    • Requer CONFIG_RPS e vem habilitado por padrão em SMP
    • A configuração é feita com a bitmap de CPUs em /sys/class/net/<dev>/queues/rx-<n>/rps_cpus
    • Pode ser desnecessário se já houver RSS, mas pode ser útil quando há mais CPUs do que filas
    • RFS (Receive Flow Steering) estende o RPS até a localidade da aplicação
    • O RPS distribui pacotes com base em fluxo, mas não considera em qual CPU a aplicação em espaço de usuário está sendo executada
    • O RFS mantém uma tabela global fluxo-para-CPU chamada rps_sock_flow_table
    • É possível ajustar o tamanho da tabela com net.core.rps_sock_flow_entries
    • A rps_dev_flow_table por fila é usada para reduzir problemas de ordenação incorreta causados por pacotes remanescentes quando o escalonador move a aplicação para uma nova CPU
    • aRFS (Accelerated RFS) é um mecanismo de balanceamento de carga com aceleração por hardware para o RFS
    • Como envia os pacotes diretamente para uma CPU próxima da thread que consome os dados, pode oferecer desempenho melhor que o RFS
    • Requer ndo_rx_flow_steer, filtragem ntuple da NIC e CONFIG_RFS_ACCEL
    • O mapeamento entre CPU e filas é derivado automaticamente da afinidade de IRQ de cada fila de recepção, portanto não é necessária configuração adicional

Ajuste de softIRQ, qdisc e buffers TCP

  • Orçamento de softIRQ

    • A rotina de polling NAPI é limitada por netdev_budget_usecs, netdev_budget e dev_weight para evitar que o softIRQ monopolize a CPU
    • O valor padrão de net.core.netdev_budget é 300, o que significa esvaziar 300 mensagens da NIC antes de o processo de softIRQ sair da CPU
    • net.core.netdev_budget_usecs é o número máximo de microssegundos de um ciclo de polling NAPI
    • net.core.dev_weight é o número máximo de pacotes por CPU que o kernel pode processar em uma interrupção NAPI
    • Se colunas além da 1ª estiverem aumentando em /proc/net/softnet_stat, pode ser necessário alterar o budget, embora pequenos aumentos possam ser normais
  • qdisc de ingress e netdev_max_backlog

    • netdev_max_backlog é uma fila interna do kernel onde o tráfego fica armazenado após ser recebido pela NIC e antes de ser processado pela pilha de protocolos, como IP/TCP
    • Há uma backlog queue para cada núcleo de CPU
    • Se a interface receber pacotes mais rápido do que o kernel consegue processar, a fila do lado de INPUT enche até netdev_max_backlog, e o excedente é descartado
    • O valor padrão é 1000, e pode ser insuficiente para várias interfaces de 1 Gbps ou uma única interface de 10 Gbps
    • A 2ª coluna de /proc/net/softnet_stat é um contador que aumenta por overflow da backlog queue
    • A alteração do valor é feita com sysctl -w net.core.netdev_max_backlog <value>
  • qdisc de egress, txqueuelen, default_qdisc

    • txqueuelen define a quantidade de pacotes permitida na fila de transmissão do kernel do dispositivo de interface de rede
    • O valor padrão pode ser 1000, dependendo do driver da interface
    • Altere com ifconfig <interface> txqueuelen value e verifique RX/TX dropped em ip -s link
    • default_qdisc é a disciplina de enfileiramento padrão a ser usada pelos dispositivos de rede
    • Em vez de pfifo_fast, é possível definir alternativas como sfq, codel e fq_codel
    • Verifique métricas como dropped, overlimits e requeues em tc -s qdisc ls dev <interface>
  • Buffers de leitura/escrita TCP e filas de conexão

    • tcp_rmem e tcp_wmem definem, respectivamente, os valores mínimo, padrão e máximo dos buffers TCP de recepção e transmissão
    • A alteração é feita assim
      • sysctl -w net.ipv4.tcp_rmem="min default max"
      • sysctl -w net.ipv4.tcp_wmem="min default max"
    • Verifique o estado de uso dos buffers com /proc/net/sockstat
    • A accept queue e a SYN queue são afetadas por net.core.somaxconn e net.ipv4.tcp_max_syn_backlog
    • net.core.somaxconn é o limite superior do parâmetro backlog de listen(), e ao alterar esse valor a aplicação também deve ser ajustada para um valor compatível
    • net.ipv4.tcp_syncookies ativa ou desativa SYN cookies, úteis para proteção contra ataques SYN flood
    • net.ipv4.tcp_congestion_control define o algoritmo de congestion control a ser usado em novas conexões

NUMA e desempenho de rede

  • NUMA (Non-uniform memory access) é uma arquitetura de memória na qual o processador pode acessar a memória local mais rapidamente do que a memória não local
  • No processamento de rede, como a CPU precisa acessar a memória do ring buffer, a localidade NUMA pode afetar o desempenho da rede
  • NUMA divide CPU, memória e dispositivos em vários nodes, funcionando como vários computadores pequenos com interconexão rápida e um sistema operacional em comum
  • Em sistemas NUMA, o objetivo do ajuste é concentrar as interrupções do dispositivo nos núcleos de CPU do único node ao qual esse dispositivo pertence
  • No entanto, sistemas NUMA podem interagir mal com aplicações em tempo real e criar latências inesperadas de eventos
  • Os nodes NUMA podem ser verificados em /sys/devices/system/node/node*
  • A localidade do dispositivo pode ser verificada em /sys/class/net/<interface>/device/numa_node
    • -1 significa que a plataforma de hardware não é realmente NUMA, ou que o kernel está emulando NUMA, ou ainda que o dispositivo não tem localidade NUMA
  • O kernel Linux oferece suporte a NUMA desde a versão 2.5, e distribuições baseadas em RedHat e Debian fornecem numactl e numad
  • numad monitora a topologia do sistema e o uso de recursos, e tenta posicionar processos com carga suficientemente grande de memória e CPU na localidade NUMA mais eficiente

Opções para processamento de pacotes mais rápido

  • AF_PACKET v4 e PACKET_MMAP

    • AF_PACKET v4 é uma interface rápida de pacotes do Linux, que elimina system calls do caminho de dados e, por padrão, usa o modo de cópia
    • Com PACKET_ZEROCOPY, é possível usar o modo true zero-copy, que mapeia o buffer de pacotes DMA no espaço do usuário
    • O caminho comum de file read seguido de socket send exige troca de contexto entre user mode e kernel mode, além de várias cópias de dados
    • zero-copy melhora o desempenho ao eliminar cópias redundantes de dados
    • PACKET_MMAP é uma API do Linux para packet sniffing rápido
    • Fornece um ring buffer mapeado em memória compartilhado entre o espaço do usuário e o kernel
    • Reduz system calls e cópias entre espaço do usuário e kernel em pacotes de envio e recebimento
  • DPDK

    • DPDK (Data Plane Development Kit) é um framework de drivers e bibliotecas em espaço do usuário para processamento rápido de pacotes
    • O objetivo é trocar pacotes de rede em velocidade nativa entre a NIC e a aplicação de usuário
    • O alvo são NICs de 10Gb ou 40Gb, e a velocidade é o critério mais importante
    • O foco é packet forwarding, não a pilha de rede
    • Quando o DPDK controla a NIC, todo o tráfego desvia do kernel, e essa NIC deixa de ser visível para o kernel
    • As portas são desvinculadas do driver do kernel Linux e passam a ser gerenciadas por drivers como vfio_pci, igb_uio e uio_pci_generic
    • Depois disso, a comunicação entre a aplicação e a NIC fica a cargo do DPDK PMD
    • O DPDK exige configuração de hugepages para alocar grandes blocos de memória
    • Componentes principais:
      • EAL: interface genérica que oculta diferenças de ambiente
      • librte_ring: API FIFO lockless com múltiplos produtores e múltiplos consumidores
      • librte_mempool: alocação de pool de objetos de memória
      • librte_mbuf: criação e manipulação de buffers para armazenar pacotes de rede
      • librte_timer: serviço de timer para execução de funções assíncronas
      • PMD: driver em que a CPU faz polling contínuo da NIC em vez de usar interrupções
    • Limitações:
      • Grande dependência de hardware
      • É preciso dedicar núcleos de CPU para executar o PMD, e ele usa 100% da CPU
  • PF_RING

    • PF_RING é um módulo do kernel Linux e um framework em espaço do usuário para processar pacotes em alta velocidade e fornecer uma API consistente para aplicações de processamento de pacotes
    • PF_RING usa o Linux NAPI para fazer polling de pacotes na NIC
    • O NAPI copia os pacotes da NIC para o circular buffer do PF_RING, e a aplicação em espaço do usuário lê os pacotes do ring
    • Nessa estrutura, há dois pollers, a aplicação e o NAPI, então ciclos de CPU são consumidos com polling
    • A vantagem é que os pacotes de entrada podem ser distribuídos simultaneamente para vários rings
    • Por ter estrutura modular, é possível usar componentes adicionais como o módulo ZC, módulo de placa baseada em FPGA, módulo Stack, módulo Timeline e módulo Sysdig
    • O PF_RING reduziu o custo de packet capture e de forwarding em userland, mas o desempenho ideal ainda é limitado por essa estrutura de dois atores, em que o kernel copia da NIC para o ring e o userland lê do ring para processar
    • Desde a versão 7.5, o PF_RING inclui suporte a adaptador AF_XDP
  • XDP e AF_XDP

    • XDP (eXpress Data Path) é uma implementação de eBPF que intercepta pacotes em um estágio inicial do caminho de dados de rede do Linux
    • O XDP processa diretamente a página do pacote RX dentro da função RX do driver de dispositivo, antes da alocação de SKB
    • eBPF é um bytecode sandboxed personalizado executado no kernel
    • Usa 11 registradores de 64 bits e uma stack de 512 bytes
    • Com backend LLVM, é possível compilar para eBPF a partir de C, Lua, Go, P4, Rust e outras linguagens
    • Fornece verifier e compilador JIT no kernel, além de suportar recursos como map, tail call e helper
    • Casos de uso do XDP:
      • pre-stack filtering para mitigação de DoS
      • forwarding e load balancing
      • técnicas de batching como GRO
      • flow sampling e monitoring
      • processamento de ULP
    • O XDP não é kernel bypass, mas sim um fast path dentro da pilha do kernel, e não substitui a pilha TCP/IP
    • Não exige hardware dedicado, mas há requisitos como NIC com múltiplas filas, TX/RX checksum offload, RSS e TSO
    • Vantagens do XDP em relação ao DPDK:
      • é possível escolher entre busy polling e rede orientada a interrupções
      • não exige huge pages
      • não há requisitos de hardware especial
      • CPU dedicada não é obrigatória
      • não é necessário reinjetar pacotes no kernel a partir de aplicações userspace de terceiros
      • não é necessário um novo modelo de segurança para acesso ao hardware de rede
      • não são necessários código/licenciamento de terceiros
    • AF_XDP é um novo tipo de socket introduzido no Linux 4.18
    • Sem contornar completamente o kernel, ele pode aproveitar recursos do kernel para criar uma estrutura semelhante à do DPDK ou do AF_PACKET
    • Um programa XDP pode redirecionar frames com eBPF para um buffer de memória em espaço do usuário
    • A transferência por DMA usa memória de espaço do usuário para oferecer suporte a zero-copy
    • Pode alcançar ganho de desempenho de 3 a 20 vezes em relação ao AF_PACKET
    • Limitações:
      • é um projeto relativamente novo
      • para suporte completo, é necessário Linux kernel 5.4 ou superior

1 comentários

 
GN⁺ 2024-07-29
Comentários do Hacker News
  • Teria sido um material realmente útil se eu tivesse visto algumas semanas atrás
    Eu queria fazer criptografia de link L2 entre datacenters e pedi cotações de appliances de hardware a vários fornecedores, mas achei o custo alto demais e resolvi construir por conta própria
    Configurei hardware de uso geral para transportar frames Ethernet sobre uma rede overlay WireGuard e entregar 10Gbps; depois de cerca de dez dias de trabalho, implementei algo aproximadamente 70% mais barato que a proposta mais barata e cerca de 95% mais barato que a mais cara, mas isso exigiu muita leitura detalhada de documentação e experimentação
    Quero usar o conteúdo deste artigo para validar se meu entendimento está correto e, à primeira vista, ele parece promissor e abrangente

    • Fiquei curioso: qual era o caso de uso em que um túnel L3 não teria sido suficiente?
    • Se puder compartilhar o código, eu gostaria de ver. Tenho muita curiosidade sobre como você implementou isso
  • Com tantos valores ajustáveis assim, parece que valeria a pena criar um software de autotuning
    Parece possível uma abordagem meio parecida com descida de gradiente: escolher aleatoriamente um parâmetro de uma whitelist, aumentar ou reduzir um pouco dentro da faixa permitida, medir o desempenho por algum tempo e reverter se piorar, ou ajustar mais se melhorar

  • É interessante, mas, como engenheiro de software, quase nunca tenho oportunidade de executar de fato os comandos mostrados no artigo
    A maioria dos sistemas roda em contêineres que são uma versão reduzida de algum Linux, não há acesso shell aos sistemas de produção, e os ambientes de desenvolvimento ou QA são tão diferentes da produção em termos de carga que reproduzir bugs geralmente não ajuda muito
    No fim, a chance de executar os comandos do artigo é mais quando mexo em sistemas pessoais; parece algo útil para quem trabalha como engenheiro de plataforma

    • A maior parte dos recursos de baixo nível provavelmente nem funcionará ou será inútil de qualquer forma. Implementações de interface de rede em contêineres normalmente fazem você lidar com pares veth e fazem todo tipo de processamento estranho no espaço de usuário
      Uma das coisas de que menos gosto no Kubernetes é o modelo de rede. Ele assume que há apenas uma placa de rede e que as aplicações são simples o bastante para não precisarem conhecer as camadas abaixo
      O modelo de rede como um todo parece ter bastante espaço para uma grande reformulação ao estilo dos anos 2020, visando simplificação e melhoria
    • Se houver um ambiente de staging o mais parecido possível com produção, pode ser útil, dependendo da situação, porque você consegue experimentar e analisar em um ambiente semelhante à produção ao qual tem acesso
  • net.core.wmem_max é descrito como o limite superior do tamanho do buffer de envio TCP, e também existe net.ipv4.tcp_wmem, então tenho duas dúvidas

    1. Por que não há um valor correspondente para IPv6? 2. Qual é a diferença em relação a net.core.wmem_max?
    • net.core.wmem_max é, como o nome diz, o valor máximo
      net.ipv4.tcp_wmem é uma tripla com três valores: mínimo, padrão e máximo; o máximo especificado aqui não pode exceder o net.core.wmem_max acima
      TCP deve ser o mesmo protocolo, seja transportado por IPv4 ou por IPv6
      Ex.: https://docs.redhat.com/en/documentation/red_hat_data_grid/7...
  • O que ficou um pouco de fora aqui é depuração e tuning para throughput acima de 100Gbps
    Ao servir HTTP nessa escala, o primeiro gargalo normalmente é a largura de banda de memória, então muitas vezes kTLS se torna necessário
    Ferramentas como o AMD μProf são muito úteis para depuração, e profiling contínuo baseado em eBPF também ajuda a entender exatamente o que está acontecendo no kernel e no espaço de usuário

  • Parece bem legal. Até agora, na minha carreira, sempre que precisei de desempenho, geralmente comecei por bypass do kernel