A Pilha TCP/IP e a Física da Rede
por Frank de Alcantara em 07/08/2026
Nesta série, a curiosa leitora vai construir o conhecimento que suporta a disciplina de redes a partir do ponto de vista de quem escreve software, e não de quem configura redes e sistemas. Isso não significa que será uma versão diluída. Significa uma versão em que cada mecanismo aparece junto com a decisão de arquitetura que ele condiciona, e em que cada afirmação vem com o número que a sustenta. Pelo menos, eu vou tentar.
Índice da Série: Redes para Engenharia de Software
- 1. A Pilha TCP/IP e a Física da Rede (Você está aqui)
- 2. Transporte: TCP, UDP e QUIC
Para construir essa perspectiva, começamos pela parte que nenhuma abstração consegue remover: o tempo físico da comunicação. Existe uma classe de defeito que nenhum profiler de aplicação encontra, porque a aplicação não está lenta; ela está esperando. O perfil mostra três microssegundos de CPU e duzentos milissegundos de relógio, mas a diferença não aparece em lugar nenhum do código. Ela está no fio, na fila de um comutador e na distância entre São Paulo e a Virgínia do Norte. Sem decompor essas parcelas, a engenheira corre o risco de otimizar justamente o que já era rápido.
A neófita leitora deve saber que o combinado desta série é o mesmo das séries Transformers, Inteligência Artificial Aplicada e Estatística Orientada à Ciência de Dados: os exemplos de código são em C++23, completos e compiláveis, e a leitora refaz na linguagem que preferir. Os laboratórios de simulação da disciplina rodam no navegador, sem instalar nada, na suíte NetworkLabs SE.
Se a leitora concordar, podemos começar pelas duas representações que organizam o vocabulário da disciplina.
1. Duas pilhas e uma decisão de engenharia
Todo curso de redes começa desenhando sete camadas empilhadas, e boa parte dos alunos sai achando que a Internet tem sete camadas. Ela não tem. Sinto muito.
O modelo OSI, de Open Systems Interconnection (interconexão de sistemas abertos), foi publicado pela ISO em 1984 como referência conceitual, e nasceu de um esforço de padronização que competia com a pilha que já estava rodando. A pilha que estava rodando venceu. Quem diria? O modelo perdedor sobreviveu como vocabulário, e é por isso que engenheiros ainda dizem problema de camada 3 ou balanceador de camada 7 sem nenhum constrangimento.
O modelo que efetivamente roda é o TCP/IP, descrito na RFC 1122 em quatro camadas: enlace, Internet, transporte e aplicação. A correspondência com o OSI é aproximada, e a aproximação falha exatamente onde importa. As camadas de sessão e apresentação do OSI, a quinta e a sexta, não têm implementação separada na Internet: o que elas descrevem virou responsabilidade da aplicação, ou de bibliotecas dentro dela. Quando alguém diz que TLS é camada 6, está fazendo uma analogia útil e imprecisa, porque TLS roda sobre TCP e é falado pela aplicação.
A Tabela 1 registra a correspondência que a série usará daqui em diante, com um exemplo por linha para que ela não fique abstrata.
| OSI | TCP/IP | O que decide | Exemplo |
|---|---|---|---|
| 7 aplicação, 6 apresentação, 5 sessão | aplicação | o significado dos bytes trocados | HTTP, DNS, gRPC, MQTT |
| 4 transporte | transporte | se há entrega ordenada e confiável, e para qual processo | TCP, UDP, QUIC |
| 3 rede | Internet | qual caminho o pacote toma entre redes | IP, ICMP, BGP |
| 2 enlace, 1 física | enlace | como o bit atravessa um meio compartilhado | Ethernet, Wi-Fi, fibra |
Tabela 1: correspondência aproximada entre OSI e TCP/IP. As camadas 5 e 6 do OSI não têm implementação separada na pilha real, e é aí que a analogia deixa de valer.
Os nomes da tabela, porém, ainda obrigam a leitora a reconstruir mentalmente onde a correspondência é direta e onde várias funções convergem. A Figura 1 torna essa diferença espacial: as camadas 7, 6 e 5 do OSI desembocam em Aplicação no TCP/IP, enquanto as camadas 2 e 1 desembocam em Enlace. As setas representam a correspondência entre os modelos, não o caminho percorrido pelos dados.
Figura 1: As sete camadas do OSI não são sete componentes separados da Internet. Na pilha TCP/IP, três funções superiores convergem em Aplicação e as duas inferiores, em Enlace.
Essa compressão esclarece o vocabulário, mas ainda não explica por que as fronteiras foram colocadas nesses pontos. A pergunta que interessa a quem escreve software, portanto, não é apenas quantas camadas existem, mas por que a divisão está exatamente aí. A resposta está em um artigo de 1984 de Saltzer, Reed e Clark que continua sendo a coisa mais útil já escrita sobre arquitetura de sistemas distribuídos: o argumento fim a fim.
O argumento diz o seguinte. Uma função que precisa de garantia completa, como entregar um arquivo sem corrupção, só pode ser implementada corretamente nos extremos da comunicação, com conhecimento da aplicação. Implementá-la também nas camadas baixas pode ser justificável por desempenho, nunca por correção. Se o disco do remetente corromper o arquivo antes de enviá-lo, nenhuma soma de verificação de enlace salvará ninguém. A verificação que conta é a que compara o arquivo lido no destino com o que o remetente pretendia enviar.
A consequência prática é uma rede burra no meio e inteligente nas pontas. O IP não promete entrega, não promete ordem e não promete integridade; ele promete tentativa. Essa pobreza deliberada é o que permitiu que a mesma camada 3 sobrevivesse à passagem de enlaces de nove mil bits por segundo para enlaces de quatrocentos gigabits por segundo, e de aplicações de terminal remoto para videoconferência. Uma camada que promete pouco é difícil de tornar obsoleta.
A atenta leitora deve guardar essa ideia, porque ela reaparece disfarçada em todos os artigos seguintes. Quando o Artigo 12 mostrar um service mesh interceptando cada requisição para acrescentar repetição, tempo limite e telemetria, valerá perguntar se a função foi colocada no lugar certo, ou se estamos reimplementando no meio o que só a ponta pode garantir.
Há, porém, um limite que o argumento fim a fim não remove, e é dele que trata o resto deste artigo. Nenhuma decisão de camada altera a velocidade da luz, o tamanho de uma fila ou o número de bits que cabem em um microssegundo de fio. Essas três coisas formam o piso sobre o qual todo o resto é construído, e a próxima seção começa medindo a primeira delas.
2. Encapsulamento e o custo de cada cabeçalho
Cada camada embrulha o que recebe da camada de cima. A aplicação entrega um payload, o transporte acrescenta um cabeçalho, a camada de Internet acrescenta outro, o enlace acrescenta o seu e ainda um encerramento. O resultado atravessa o fio como uma boneca russa, e é desmontado na ordem inversa no destino.
Precisamos de um número antes de prosseguir. A MTU, de Maximum Transmission Unit (unidade máxima de transmissão), é o maior pacote da camada de Internet que o enlace transporta sem fragmentação. Na Ethernet convencional, a MTU é de $1500$ bytes: um pacote IPv4 ou IPv6 de até $1500$ bytes ocupa o campo de dados do quadro, enquanto o cabeçalho e a sequência de verificação da própria Ethernet ficam fora dessa conta. Declarar essa fronteira evita a confusão entre o tamanho do pacote IP, o tamanho do quadro e o tempo efetivamente ocupado na linha.
Antes de qualquer conta, é preciso dizer o que estamos contando, porque a mesma pergunta admite duas respostas diferentes conforme a fronteira escolhida. Definamos a eficiência de quadro como a fração dos bytes que atravessam o fio carregando dado útil da aplicação:
\[\eta = \frac{b_{\text{útil}}}{b_{\text{útil}} + b_{\text{env}}},\]na qual $b_{\text{útil}}$ é o número de bytes de payload da aplicação e $b_{\text{env}}$ é o envelope, isto é, a soma dos bytes acrescentados por todas as camadas. Para TCP sobre IPv4 sobre Ethernet, sem opções em nenhum dos três, o envelope tem tamanho fixo:
\[b_{\text{env}} = \underbrace{20}_{\text{IPv4}} + \underbrace{20}_{\text{TCP}} + \underbrace{18}_{\text{Ethernet}} = 58\ \text{bytes}\]nos quais os $18$ bytes de Ethernet são $14$ de cabeçalho, com endereços de origem e destino e tipo, mais $4$ de sequência de verificação. O preâmbulo e o delimitador de início somam $8$ bytes, e o intervalo entre quadros consome o tempo equivalente a mais $12$ bytes. Esses $20$ bytes não fazem parte do comprimento do quadro, mas ocupam a linha; por isso, entram nos cálculos de pacotes por segundo e de goodput, como o do exercício 4.
Com uma MTU de $1500$ bytes, o maior payload de aplicação é $1500 - 40 = 1460$ bytes. Esse valor tem nome próprio, MSS, de Maximum Segment Size (tamanho máximo de segmento). O quadro correspondente ocupa $1460 + 58 = 1518$ bytes no fio, e a eficiência é
\[\eta_{\text{cheio}} = \frac{1460}{1518} = 0{,}9618 = 96{,}18\%\]Um resultado confortável, que produz a impressão errada de que cabeçalho é detalhe. Registro aqui, porque a leitora vai encontrar o número em toda parte, que a razão $1460/1500 = 97{,}33\%$ também circula como “eficiência”: ela mede a fração da MTU, ignorando o quadro Ethernet. As duas respostas estão certas para perguntas diferentes, e misturá-las na mesma tabela é uma forma barata de errar por um ponto percentual sem saber onde.
Refaçamos a conta para um payload de $64$ bytes, tamanho típico de uma mensagem de telemetria ou de um reconhecimento de aplicação. O envelope não mudou, porque ele não depende do que carrega:
\[\eta_{64} = \frac{64}{64 + 58} = \frac{64}{122} = 0{,}5246 = 52{,}46\%\]Quase metade do fio transporta metadados. Os mesmos $58$ bytes que consumiam $3{,}82\%$ do quadro cheio consomem agora $47{,}54\%$. A esperta leitora percebe que a eficiência não é uma propriedade do protocolo: é uma propriedade da razão entre o tamanho da mensagem e o tamanho fixo do envelope. Protocolo nenhum é eficiente ou ineficiente em abstrato; ele é eficiente para uma distribuição de tamanhos de mensagem, e essa distribuição é uma decisão da aplicação. Guardemos isso, porque o Artigo 14 vai comparar REST, gRPC e WebSocket exatamente com essa régua, e o Artigo 15 vai mostrar protocolos desenhados por gente que contava bytes.
A Figura 2 mostra os dois regimes lado a lado, com a mesma MTU e payloads de tamanhos diferentes.
Figura 2: Os mesmos 58 bytes de envelope consomem 3,82% de um quadro cheio e 47,54% de um quadro com payload de 64 bytes. A eficiência não é propriedade do protocolo, e sim da razão entre mensagem e envelope.
Há um caso em que a conta muda por decisão de projeto e não de aplicação. O cabeçalho fixo do IPv6 tem $40$ bytes, o dobro do IPv4, porque os endereços passaram de quatro para dezesseis bytes cada. Mantida a MTU de $1500$ bytes, o payload máximo cai para $1440$ e o envelope sobe para $78$ bytes, com o quadro continuando a ocupar $1518$ bytes no fio:
\[\eta_{\text{IPv6}} = \frac{1440}{1518} = 94{,}86\%,\]uma perda de $1{,}32$ ponto percentual. É pouco, e compra um espaço de endereçamento imensamente maior. O Artigo 9 mostrará por que essa troca se tornou necessária.
Falta o caso patológico. Se o bit DF, de Don’t Fragment (não fragmentar), permitir, um pacote IPv4 maior que a MTU pode ser fragmentado pela origem ou por um roteador. Um datagrama de $4000$ bytes, com $20$ bytes de cabeçalho e $3980$ bytes de dados, torna-se três pacotes IPv4 de $1500$, $1500$ e $1040$ bytes. A soma na camada de Internet é, portanto, $4040$ bytes. Quando colocamos cada fragmento em um quadro Ethernet, a soma passa a $4094$ bytes; incluindo preâmbulo e intervalo entre quadros, a ocupação da linha chega a $4154$ bytes. O número $4040$ mede tráfego IPv4, não bytes no fio.
Os $40$ bytes adicionais de cabeçalho IP são pequenos. A fragilidade nasce da remontagem: se um fragmento faltar, a camada de Internet não entrega o datagrama incompleto à camada superior. O efeito posterior depende do transporte. O UDP não retransmite automaticamente; já o TCP detecta que os bytes não foram confirmados e retransmite o segmento correspondente, que pode voltar a ser fragmentado. A RFC 8900 recomenda que protocolos de camadas superiores reduzam sua dependência da fragmentação justamente porque perda, filtragem por equipamentos intermediários e estado de remontagem tornam o mecanismo frágil.
No IPv6, a regra muda: roteadores não fragmentam pacotes. Se o próximo enlace não comportar o pacote, o roteador o descarta e envia uma mensagem ICMPv6 Packet Too Big; somente a origem pode criar fragmentos. A distinção explica por que descobrir a MTU do caminho e dimensionar mensagens antes do envio é parte da correção, não uma otimização tardia.
2.1 Exercícios da Seção 2
1. Calcule a eficiência de um quadro cheio com TCP sobre IPv4
Uma MTU de $1500$ bytes transporta um segmento TCP sobre IPv4 sobre Ethernet, sem opções em nenhuma camada. Qual fração dos bytes no fio carrega dado da aplicação? E qual fração da MTU?
Solução: O envelope soma $20 + 20 + 18 = 58$ bytes e o payload máximo é o MSS, $1500 - 40 = 1460$ bytes. O quadro ocupa $1518$ bytes no fio, portanto
\[\eta = \frac{1460}{1518} = 96{,}18\%, \qquad \eta_{\text{MTU}} = \frac{1460}{1500} = 97{,}33\%.\]Os $58$ bytes de envelope consomem $3{,}82\%$ do que atravessa o fio. Este é o melhor caso possível para esta combinação de protocolos e é o número que costuma ser citado quando alguém quer argumentar que cabeçalho não importa. Repare que as duas frações diferem em $1{,}15$ ponto percentual apenas porque contam fronteiras diferentes, e que citar uma delas sem dizer qual é a origem de metade das discussões inúteis sobre eficiência de rede. O exercício 3 mostra o que acontece com o mesmo argumento em outro regime.
2. Refaça o cálculo para IPv6
O cabeçalho fixo do IPv6 tem $40$ bytes. Qual a nova eficiência no fio e qual a diferença em pontos percentuais?
Solução: Com $40$ bytes de IPv6, $20$ de TCP e $18$ de Ethernet, o envelope sobe para $78$ bytes e o payload máximo cai para $1500 - 60 = 1440$ bytes. O quadro continua ocupando $1440 + 78 = 1518$ bytes no fio:
\[\eta_{\text{IPv6}} = \frac{1440}{1518} = 94{,}86\%.\]A diferença é de $96{,}18 - 94{,}86 = 1{,}32$ ponto percentual. Tanto o quadro IPv4 cheio quanto o quadro IPv6 cheio ocupam o equivalente a $1538$ bytes na linha, porque os $20$ bytes adicionais do cabeçalho IPv6 substituem $20$ bytes de dados da aplicação. Em um enlace de $1$ Gbit/s, a taxa de $10^{9}/(1538 \times 8) = 81\,274$ quadros por segundo permanece a mesma; o que cai é o goodput. A perda é de $20 \times 81\,274 = 1\,625\,480$ bytes/s, ou aproximadamente $1{,}63$ MB/s de dados úteis. O custo é mensurável, mas não representa tráfego adicional na linha.
3. Calcule a eficiência de um payload de 64 bytes
Uma mensagem de telemetria carrega $64$ bytes de dados sobre TCP e IPv4, dentro de um quadro Ethernet cujos cabeçalho e encerramento somam $18$ bytes. Qual a eficiência?
Solução: O envelope continua com $58$ bytes, e o quadro completo tem $64 + 58 = 122$ bytes.
\[\eta = \frac{64}{122} = 0{,}5246 = 52{,}46\%\]Menos de $53\%$ do que atravessa o fio é dado da aplicação. Comparado ao quadro cheio do exercício 1, a eficiência caiu $96{,}18 - 52{,}46 = 43{,}72$ pontos percentuais sem que nenhum protocolo tenha mudado. Mudou apenas o tamanho da mensagem. A conclusão de engenharia é direta: agrupar mensagens pequenas em mensagens maiores é uma otimização de rede antes de ser uma otimização de aplicação, e é a razão de existirem quase todos os mecanismos de agrupamento que a leitora encontra em bibliotecas de cliente.
4. Determine a taxa de pacotes de um enlace de 10 Gbit/s com quadros mínimos
O menor quadro Ethernet tem $64$ bytes, e cada quadro no fio é precedido por $8$ bytes de preâmbulo e seguido por um intervalo entre quadros equivalente a $12$ bytes, totalizando $84$ bytes de ocupação. Quantos pacotes por segundo um enlace de $10$ Gbit/s precisa processar no pior caso, e quanto tempo há por pacote?
Solução: Cada quadro ocupa $84 \times 8 = 672$ bits do fio. A taxa é
\[\lambda_{\max} = \frac{10 \times 10^{9}}{672} = 14{,}881 \times 10^{6}\ \text{pacotes/s},\]o clássico valor de $14{,}88$ Mpps. O orçamento por pacote é o inverso:
\[\frac{1}{14{,}881 \times 10^{6}} = 67{,}2\ \text{ns}.\]| Grandeza | Resultado |
|---|---|
| ocupação por quadro | $672$ bits |
| taxa máxima | $14{,}88$ Mpps |
| intervalo por pacote | $67{,}2$ ns |
O resultado, $67{,}2$ nanossegundos, coloca o processamento na mesma ordem de grandeza de operações de memória que escapam dos caches, embora o custo exato dependa da máquina. Portanto, uma única espera longa pela memória pode consumir parte relevante do orçamento de um pacote. Essa escala ajuda a explicar a existência de DPDK, XDP e eBPF, que o Artigo 5 apresentará, e mostra por que processar pacotes em taxa de linha é também um problema de arquitetura de memória. A leitora que acompanhou a série Transformers reconhecerá a estrutura: também ali o gargalo raramente era a aritmética isolada.
5. Analise a fragmentação de um datagrama de 4000 bytes
Um datagrama IPv4 de $4000$ bytes, com cabeçalho mínimo de $20$ bytes e bit DF desativado, atravessa um enlace Ethernet com MTU de $1500$ bytes. Quantos fragmentos são gerados? Calcule separadamente o total de bytes na camada IPv4, nos quadros Ethernet e na ocupação da linha, incluindo preâmbulo e intervalo entre quadros. Por fim, explique o efeito da perda de um único fragmento para UDP e TCP.
Solução: O datagrama original tem $20$ bytes de cabeçalho e $3980$ bytes de dados. Cada fragmento carrega seu próprio cabeçalho de $20$ bytes, restando $1480$ bytes para dados, e o deslocamento de fragmento é medido em múltiplos de oito bytes, o que exige que todos os fragmentos, exceto o último, transportem um múltiplo de oito. O maior múltiplo de oito menor ou igual a $1480$ é o próprio $1480$.
| Fragmento | Dados IPv4 | Deslocamento | Pacote IPv4 | Quadro Ethernet | Ocupação da linha |
|---|---|---|---|---|---|
| 1 | $1480$ | $0$ | $1500$ | $1518$ | $1538$ |
| 2 | $1480$ | $185$ | $1500$ | $1518$ | $1538$ |
| 3 | $1020$ | $370$ | $1040$ | $1058$ | $1078$ |
| Total | $3980$ | $4040$ | $4094$ | $4154$ |
São três fragmentos. Na camada IPv4, os dois cabeçalhos adicionais elevam o total de $4000$ para $4040$ bytes, um acréscimo de $1{,}0\%$. A Ethernet acrescenta $18$ bytes a cada um dos três fragmentos, levando os quadros a $4094$ bytes; preâmbulos e intervalos elevam a ocupação da linha a $4154$ bytes.
Se cada fragmento tiver probabilidade independente $p$ de perda, o datagrama chegará completo com probabilidade $(1-p)^3$. Para $p=0{,}01$, a probabilidade de falha será $1-0{,}99^3=2{,}97\%$. Quando um fragmento faltar, a camada IP abandonará a remontagem. O UDP não oferecerá retransmissão por conta própria, enquanto o TCP acabará retransmitindo os bytes não confirmados. Portanto, a perda de um fragmento invalida o datagrama inteiro, mas a reação observada pela aplicação depende do protocolo de transporte.
3. Latência: os quatro somandos
Latência é a palavra que a indústria usa para tudo que demora, e é justamente por isso que ela precisa ser decomposta antes de ser usada. Em um caminho com $h$ enlaces, o atraso de um pacote soma propagação e transmissão em cada enlace, além de fila e processamento em cada equipamento intermediário:
\[T_{\text{fim a fim}} = \sum_{\ell=1}^{h}\left(\frac{d_\ell}{v_\ell}+\frac{L_\ell}{R_\ell}\right) + \sum_{k=1}^{h-1}\left(q_k+p_k\right),\]na qual $d_\ell$ é o comprimento do enlace $\ell$, $v_\ell$ é a velocidade de propagação no meio, $L_\ell$ é o número de bits transmitidos nesse enlace, $R_\ell$ é sua taxa, $q_k$ é a espera na fila do equipamento $k$ e $p_k$ é o processamento naquele equipamento. Quando reunimos parcelas da mesma natureza, recuperamos a forma abreviada $T=T_{\text{prop}}+T_{\text{trans}}+T_{\text{fila}}+T_{\text{proc}}$. A abreviação é útil, mas a soma por enlace impede que esqueçamos que um pacote é serializado novamente a cada salto.
O tempo de propagação é o tempo que o sinal leva para percorrer a distância física:
\[T_{\text{prop}} = \frac{d}{v}\]na qual $d$ é a distância percorrida pelo meio e $v$ é a velocidade de propagação nesse meio. Em fibra óptica, $v = c/n$, com $c = 299\,792{,}458$ km/s e índice de refração $n \approx 1{,}5$, o que dá $v \approx 199\,862$ km/s. A série usa o valor arredondado de $200\,000$ km/s, e diz sempre quando o arredondamento importa, o que quase nunca é o caso, porque o erro relativo é de $0{,}07\%$.
Um número para levar na cabeça: a $200\,000$ km/s, o sinal percorre $200$ km por milissegundo. Ou, na forma mais útil, cada $100$ km de fibra custa $0{,}5$ ms em uma direção e $1$ ms na ida e volta.
O tempo de transmissão é o tempo para empurrar todos os bits da mensagem para dentro do fio:
\[T_{\text{trans}} = \frac{L}{R},\]na qual $L$ é o tamanho da mensagem em bits e $R$ é a taxa do enlace em bits por segundo. Note a diferença estrutural em relação à propagação: $T_{\text{trans}}$ depende do tamanho da mensagem e da velocidade do enlace, e não depende da distância; $T_{\text{prop}}$ depende da distância e não depende do tamanho da mensagem nem da taxa do enlace. Elas escalam de forma independente, e confundi-las é o erro que produz a frase “vamos contratar mais banda para resolver a latência”.
Vejamos o que a independência significa em números. Transmitir $1$ MiB, que são $8\,388\,608$ bits, custa
\[T_{\text{trans}} = \frac{8\,388\,608}{10^{8}} = 83{,}9\ \text{ms a }100\ \text{Mbit/s}\]e cai para $8{,}39$ ms a $1$ Gbit/s e $0{,}839$ ms a $10$ Gbit/s. Multiplicar a taxa por cem dividiu o tempo de transmissão por cem. Enquanto isso, se o enlace tem $600$ km, $T_{\text{prop}} = 600/200\,000 = 3{,}0$ ms nos três casos. A $100$ Mbit/s a transmissão dominava com $96{,}5\%$ do total; a $10$ Gbit/s a propagação domina com $78{,}1\%$. O gargalo mudou de natureza sem que ninguém tocasse na topologia.
A Figura 3 mostra os dois regimes empilhados, com as mesmas parcelas e proporções invertidas.
Figura 3: Multiplicar a taxa do enlace por cem reduz o tempo de transmissão por cem e não reduz um único microssegundo do tempo de propagação. A partir de certa taxa, comprar banda deixa de comprar tempo.
O tempo de processamento é o gasto por cada equipamento para examinar o cabeçalho, consultar a tabela de encaminhamento e decidir a porta de saída. Esse tempo depende do equipamento, da função executada e de o pacote seguir pelo caminho rápido em silício ou cair no caminho lento em software. Para manter o exemplo verificável, adotaremos $10$ µs por salto como hipótese, não como propriedade universal. Doze saltos somam então $0{,}12$ ms, apenas $0{,}79\%$ dos $15{,}12$ ms formados por propagação e processamento em uma rota de $3000$ km. Em uma rede de longa distância, essa hipótese torna o processamento pequeno; dentro de um centro de dados, a conclusão precisa ser refeita com medições do equipamento real.
O tempo de fila não pode ser deduzido apenas da distância, da taxa e do tamanho do pacote, porque depende também do processo de chegadas e da distribuição dos tempos de serviço. Modelos de filas fornecem fórmulas quando declaramos essas hipóteses; sem elas, a folha de dados do enlace não basta. A Seção 7 fará exatamente essa passagem, primeiro com um modelo M/M/1 e depois com seus limites.
Um exercício mental fecha a seção. Existe uma distância a partir da qual a propagação supera a transmissão, e essa distância depende do tamanho do objeto e da taxa do enlace. Igualando as duas parcelas,
\[\frac{d}{v} = \frac{L}{R} \quad\Longrightarrow\quad d^{*} = \frac{L\,v}{R}.\]Para um objeto de $100$ KiB em um enlace de $1$ Gbit/s, $L = 819\,200$ bits e
\[d^{*} = \frac{819\,200 \times 200\,000}{10^{9}} = 163{,}8\ \text{km}.\]Cento e sessenta e quatro quilômetros. Depois dessa distância, a propagação supera a transmissão para esse objeto e essa taxa. Aumentar $R$ ainda reduz uma parcela, mas já não altera a parcela dominante; para reduzi-la, precisamos encurtar $d$, que é exatamente o que uma rede de distribuição de conteúdo faz e o que o Artigo 10 vai quantificar.
3.1 Exercícios da Seção 3
1. Calcule o tempo de propagação de um enlace de 600 quilômetros
Qual o tempo de propagação em fibra óptica para uma distância de $600$ km?
Solução: Com $v = 200\,000$ km/s,
\[T_{\text{prop}} = \frac{600}{200\,000} = 3{,}0 \times 10^{-3}\ \text{s} = 3{,}0\ \text{ms}.\]Com o valor mais preciso $v = 199\,862$ km/s, o resultado é $3{,}002$ ms. A diferença de dois microssegundos justifica o arredondamento em todos os cálculos desta série, exceto quando a leitora estiver comparando duas rotas que diferem em menos de $1\%$, situação em que a precisão do modelo já não é o fator limitante de qualquer maneira.
2. Calcule o tempo de transmissão de 1 MiB em três taxas
Quanto tempo leva para colocar $1$ MiB no fio a $100$ Mbit/s, $1$ Gbit/s e $10$ Gbit/s?
Solução: Um mebibyte tem $1024 \times 1024 \times 8 = 8\,388\,608$ bits. Aplicando $T_{\text{trans}} = L/R$:
| Taxa | $T_{\text{trans}}$ |
|---|---|
| $100$ Mbit/s | $83{,}9$ ms |
| $1$ Gbit/s | $8{,}39$ ms |
| $10$ Gbit/s | $0{,}839$ ms |
Observe que a série usa $\text{Mbit/s}$ como potência de dez, $10^{6}$ bits por segundo, e $\text{MiB}$ como potência de dois, $2^{20}$ bytes. As duas convenções coexistem porque taxas de enlace sempre foram contadas em potências de dez e armazenamento em potências de dois. Trocar uma pela outra introduz um erro de $4{,}86\%$ em megabytes e de $7{,}37\%$ em gigabytes, o que é suficiente para invalidar um dimensionamento e insuficiente para ser notado.
3. Determine qual parcela domina em cada regime
Para o objeto de $1$ MiB do exercício anterior, atravessando $600$ km de fibra, calcule a fração do atraso total devida à transmissão nos três regimes.
Solução: A propagação é constante em $3{,}0$ ms. Somando as duas parcelas:
| Taxa | $T_{\text{trans}}$ | $T_{\text{prop}}$ | Total | Fração de $T_{\text{trans}}$ |
|---|---|---|---|---|
| $100$ Mbit/s | $83{,}9$ ms | $3{,}0$ ms | $86{,}9$ ms | $96{,}55\%$ |
| $1$ Gbit/s | $8{,}39$ ms | $3{,}0$ ms | $11{,}39$ ms | $73{,}66\%$ |
| $10$ Gbit/s | $0{,}84$ ms | $3{,}0$ ms | $3{,}84$ ms | $21{,}85\%$ |
Passar de $100$ Mbit/s para $1$ Gbit/s cortou o atraso total de $86{,}9$ para $11{,}39$ ms, uma redução de $86{,}9\%$. Passar de $1$ para $10$ Gbit/s cortou de $11{,}39$ para $3{,}84$ ms, uma redução de $66{,}3\%$. O próximo fator de dez cortaria para $3{,}08$ ms, uma redução de apenas $19{,}7\%$. O retorno decrescente não é uma opinião sobre investimento em infraestrutura: é a consequência aritmética de somar uma parcela que encolhe a uma parcela que não encolhe.
4. Decomponha o atraso de um pacote pequeno em uma rota longa
Um pacote de $64$ bytes atravessa $3000$ km de fibra passando por doze comutadores, cada um com $10$ µs de processamento, em enlaces de $10$ Gbit/s. Decomponha o atraso.
Solução: A propagação é $3000/200\,000 = 15{,}0$ ms. O processamento é $12 \times 10 = 120$ µs $= 0{,}12$ ms. A transmissão de $64$ bytes a $10$ Gbit/s é $512/10^{10} = 51{,}2$ ns por salto; com treze transmissões, incluindo a origem, chega a $0{,}67$ µs, ou $0{,}00067$ ms. Ignorando a fila:
| Parcela | Valor | Fração |
|---|---|---|
| propagação | $15{,}0$ ms | $99{,}21\%$ |
| processamento | $0{,}12$ ms | $0{,}79\%$ |
| transmissão | $0{,}00067$ ms | $0{,}004\%$ |
A geografia responde por $99{,}21\%$ do atraso. Um engenheiro que gaste três meses reduzindo o processamento por salto de $10$ para $5$ µs terá melhorado o atraso total em $0{,}4\%$, resultado que não sobrevive nem ao ruído da medição. É o análogo de rede daquilo que a série Transformers observa sobre kernels limitados por memória: reduzir a operação errada é afiar a faca para um duelo de pistolas.
5. Encontre a distância em que a propagação passa a dominar
A partir de que distância a propagação supera a transmissão, para um objeto de $100$ KiB em um enlace de $1$ Gbit/s? E para um objeto de $1$ KiB?
Solução: Igualando $d/v = L/R$, obtemos $d^{*} = Lv/R$. Para $100$ KiB, $L = 102\,400 \times 8 = 819\,200$ bits:
\[d^{*} = \frac{819\,200 \times 200\,000}{10^{9}} = 163{,}84\ \text{km}\]Para $1$ KiB, $L = 8192$ bits e $d^{} = 1{,}638$ km. Portanto, uma mensagem desse tamanho entra no regime dominado pela propagação depois de apenas um quilômetro e meio. A distribuição de tamanhos depende da aplicação, mas a conta mostra por que chamadas curtas e frequentes deixam de responder a aumentos de banda tão logo atravessam uma região metropolitana. Essa é a justificativa quantitativa para aproximar serviços e *caches dos usuários.
4. O piso físico do RTT
O RTT, de Round-Trip Time (tempo de ida e volta), é o intervalo entre emitir uma unidade observável, como um segmento ou uma requisição, e receber a resposta ou confirmação correspondente. A definição precisa nomear o par de eventos medido: um RTT de TCP, um eco ICMP e uma consulta DNS não começam nem terminam necessariamente nos mesmos pontos do software. Ainda assim, a ida e volta é a unidade de conta de protocolos que precisam receber informação antes de prosseguir. Uma abertura TCP convencional custa um RTT; uma negociação TLS 1.3 completa sobre essa conexão custa outro; e uma resolução DNS fria pode acrescentar uma ou mais viagens, dependendo do resolvedor e do estado de seus caches.
Para comparar arquiteturas, vamos construir um limite inferior deliberadamente otimista. Seja $d_g$ a distância de grande círculo entre os extremos e seja $v_f=200\,000$ km/s a velocidade aproximada de propagação na fibra. O piso geográfico em fibra será
\[\text{RTT}_{\text{fibra}}=\frac{2d_g}{v_f}.\]Esse valor não descreve uma rota real: ele supõe uma fibra que segue a geodésica, sem equipamentos nem filas. Tampouco é um limite universal para qualquer meio, pois enlaces de micro-ondas propagam o sinal mais perto da velocidade da luz no vácuo. Dentro do modelo de uma rota em fibra, porém, qualquer RTT menor que esse piso revela coordenadas, pontos de medição ou unidades incompatíveis.
A Tabela 2 traz o piso a partir de São Paulo para cinco regiões de nuvem, com as distâncias calculadas pela fórmula do semiverseno sobre as coordenadas das cidades.
| Destino | Distância (km) | Ida (ms) | Piso do RTT (ms) |
|---|---|---|---|
| Ashburn, Virgínia, Estados Unidos | $7665$ | $38{,}3$ | $76{,}6$ |
| Frankfurt, Alemanha | $9829$ | $49{,}1$ | $98{,}3$ |
| Cidade do Cabo, África do Sul | $6345$ | $31{,}7$ | $63{,}4$ |
| Sydney, Austrália | $13\,357$ | $66{,}8$ | $133{,}6$ |
| Pequim, China | $17\,599$ | $88{,}0$ | $176{,}0$ |
Tabela 2: piso geográfico idealizado do RTT a partir de São Paulo, em fibra a $200\,000$ km/s e sobre a distância de grande círculo. Uma rota real em fibra será mais longa e acrescentará equipamentos e filas.
A palavra piso faz trabalho pesado nessa tabela. Medições reais em fibra ficam acima dele, mas não existe um percentual universal que possamos acrescentar. Em um mapa de fibras de longa distância dos Estados Unidos, Bozkurt e colaboradores encontraram razão mediana de $1{,}32$ entre o menor caminho disponível em fibra e a distância geodésica; no percentil $95$, a razão chegou a $1{,}86$. Esses valores descrevem aquele conjunto de rotas, não uma constante mundial, e servem para mostrar por que multiplicar a geodésica por um fator escolhido de memória não substitui medir.
A primeira fonte do excesso é geométrica. Cabos submarinos contornam plataformas continentais, evitam zonas sísmicas e ligam estações de amarração; cabos terrestres seguem direitos de passagem. A fibra real, portanto, não percorre o arco mínimo da Tabela 2.
A segunda é o processamento e a comutação, que a Seção 3 quantificou como pequenos por salto e que se acumulam ao longo de dezenas de saltos.
A terceira é a fila, que é variável, depende da hora do dia e é o assunto da Seção 7.
A leitora que queira verificar isso não precisa aceitar um fator pronto. A plataforma RIPE Atlas oferece medições públicas entre milhares de pontos, com histórico, enquanto a Seção 8 mostra como reduzir uma coleção de amostras sem esconder a cauda. O programa didático daquela seção não envia sondas pela rede; ele recebe amostras já coletadas. Essa separação entre coletar e analisar evita prometer ao código uma capacidade que ele não possui.
O que fazer com esses números é a parte que interessa a quem projeta software. Dentro do modelo idealizado da Tabela 2, cada ida e volta em fibra entre São Paulo e Frankfurt custa ao menos $98{,}3$ ms. Suponha, para isolar o custo da conversa, que uma resolução DNS fria acrescente um RTT equivalente e que depois venham, em sequência, um RTT de abertura TCP e um RTT de TLS. Essa arquitetura gasta
\[3 \times 98{,}3 = 294{,}9\ \text{ms}\]antes de qualquer dado. A conta não afirma que todo DNS percorre a mesma rota nem que todo protocolo exige essas três etapas; ela mostra o preço de três dependências sequenciais quando cada uma cruza a mesma distância. A aplicação, note, ainda não processou a requisição.
Inverta agora a conta, porque é assim que ela vira decisão de projeto. Um ponto de presença a $300$ km do usuário tem piso de RTT de $3{,}0$ ms. Quantas idas e voltas locais cabem no orçamento de uma única ida e volta a Frankfurt?
\[\left\lfloor \frac{98{,}3}{3{,}0} \right\rfloor = 32.\]O quociente é $32$. Isso significa que uma arquitetura local pode realizar trinta e duas idas e voltas e ainda permanecer dentro do piso geográfico idealizado de uma única ida e volta transatlântica. A comparação condensa o argumento a favor de redes de distribuição de conteúdo, caches e computação na borda, e reaparecerá com números concretos no Artigo 10.
4.1 Exercícios da Seção 4
1. Calcule o piso do RTT entre São Paulo e a Virgínia do Norte
A distância de grande círculo entre São Paulo e Ashburn, na Virgínia, é de $7665$ km. Qual o menor RTT fisicamente possível em fibra?
Solução: O tempo de ida é $7665/200\,000 = 38{,}3$ ms, e o RTT é o dobro:
\[\text{RTT}_{\min} = \frac{2 \times 7665}{200\,000} = 76{,}65\ \text{ms} \approx 76{,}6\ \text{ms}.\]Com $v = 199\,862$ km/s o resultado seria $76{,}70$ ms. Nenhuma otimização de software, nenhuma escolha de protocolo e nenhuma compra de banda produz um RTT de $50$ ms nesse par de cidades, porque isso exigiria um sinal a $306\,600$ km/s, acima da velocidade da luz no vácuo. Quando alguém prometer isso, a conversa acabou.
| Hipótese | Velocidade | RTT calculado |
|---|---|---|
| aproximação didática | $200\,000$ km/s | $76{,}65$ ms |
| valor de referência usado na conferência | $199\,862$ km/s | $76{,}70$ ms |
A diferença de $0{,}05$ ms entre as duas hipóteses é irrelevante para o argumento: ambas excluem um RTT de $50$ ms por fibra entre esses pontos. O valor continua sendo um piso geográfico idealizado, pois a rota instalada é mais longa que a distância de grande círculo.
2. Construa a tabela de pisos para cinco regiões
Calcule o piso do RTT de São Paulo para Frankfurt, Cidade do Cabo, Sydney e Pequim, com as distâncias da Tabela 2.
Solução: Aplicando $\text{RTT}_{\min} = 2d/v$ com $v = 200\,000$ km/s:
| Destino | $d$ (km) | $\text{RTT}_{\min}$ (ms) |
|---|---|---|
| Cidade do Cabo | $6345$ | $63{,}45$ |
| Ashburn | $7665$ | $76{,}65$ |
| Frankfurt | $9829$ | $98{,}29$ |
| Sydney | $13\,357$ | $133{,}57$ |
| Pequim | $17\,599$ | $175{,}99$ |
Note que a Cidade do Cabo, do outro lado do Atlântico Sul, é o destino intercontinental mais próximo de São Paulo, mais perto que a Virgínia. A intuição de que “os Estados Unidos são perto” vem da densidade de cabos e da economia, não da geografia. É um bom lembrete de que a topologia da Internet não é a topologia do planeta, tema que o Artigo 4 desenvolve ao tratar de sistemas autônomos.
3. Estime o excesso de uma medição real sobre o piso
Uma medição de $115$ ms para a Virgínia é observada de São Paulo. Qual o excesso relativo sobre o piso, e como atribuí-lo?
Solução: O excesso absoluto é $115 - 76{,}65 = 38{,}35$ ms, e o excesso relativo é
\[\frac{38{,}35}{76{,}65} = 0{,}5003 = 50{,}03\%.\]O excesso de $50{,}03\%$ não identifica sozinho a causa. Podemos, contudo, testar uma decomposição hipotética. Se a rota tiver comprimento $1{,}3$ vez maior que a geodésica, a propagação acrescentará aproximadamente $0{,}3 \times 76{,}65 = 23{,}0$ ms. Se houver trinta processamentos de $10$ µs, acrescentaremos $0{,}3$ ms. Restarão cerca de $15{,}0$ ms para filas e demais diferenças do caminho. Sem medir a rota e os saltos, esses valores não são uma atribuição; são um teste de ordem de grandeza que mostra quais hipóteses merecem instrumentação.
4. Calcule o custo de três idas e voltas sequenciais
Uma requisição exige resolução DNS fria, abertura de conexão TCP e negociação TLS antes do primeiro byte de aplicação. Qual o tempo mínimo para um usuário em São Paulo acessando Frankfurt?
Solução: Cada etapa custa ao menos uma ida e volta ao destino, e as três são sequenciais porque cada uma depende do resultado da anterior:
\[T = 3 \times 98{,}29 = 294{,}87\ \text{ms}.\]Quase trezentos milissegundos antes de o servidor receber dados da aplicação. O QUIC, que o Artigo 2 apresentará, combina a criação do transporte com a negociação criptográfica: uma conexão nova pode enviar dados protegidos após um RTT, em vez dos dois RTTs de TCP seguido de TLS 1.3; uma conexão retomada pode usar dados antecipados sob restrições de segurança. O cache de DNS remove outra dependência quando a resposta já está disponível perto da aplicação. Cada mecanismo ataca uma seta específica do caminho, e não uma latência abstrata.
5. Determine quantas idas e voltas locais cabem em uma transatlântica
Um ponto de presença a $300$ km do usuário oferece RTT de $3{,}0$ ms. Quantas idas e voltas locais cabem no orçamento de uma única ida e volta a Frankfurt?
Solução: O RTT local é $2 \times 300/200\,000 = 3{,}0$ ms. A razão é
\[\left\lfloor \frac{98{,}29}{3{,}0} \right\rfloor = 32.\]Assim, o orçamento comporta trinta e duas idas e voltas ideais de $3$ ms. Para aproximar a conta de uma arquitetura real, considere uma cadeia serial de dez chamadas internas com RTT de $0{,}5$ ms: ela acrescenta $5$ ms antes de filas e processamento. Esse custo é pequeno diante de um único RTT idealizado até Frankfurt, mas pode dominar uma requisição atendida inteiramente dentro do centro de dados ou crescer com fan-out, repetição e saturação. A comparação não absolve a arquitetura interna; apenas coloca os dois termos na mesma unidade. O Artigo 12 voltará a essa soma ao tratar dos sidecars de um service mesh.
5. Largura de banda, vazão e o produto banda-atraso
Três palavras costumam ser usadas como sinônimas e não são. A largura de banda, ou capacidade, é a taxa máxima nominal do enlace: o que está no contrato. Neste artigo, chamaremos de vazão, ou throughput, a taxa total observada na linha, contando cabeçalhos e retransmissões, e de goodput a taxa de dados novos entregues à aplicação. Outras ferramentas medem throughput em fronteiras diferentes; por isso, o nome da grandeza deve vir acompanhado do ponto de medição. Em nossa fronteira, um enlace de $1$ Gbit/s saturado com quadros cheios entrega $1$ Gbit/s de vazão e $1460/1538 \times 10^{9} = 949{,}3$ Mbit/s de goodput. Com a opção de marcação temporal do TCP, que ocupa até doze bytes incluindo preenchimento, o payload cai para $1448$ bytes e o goodput para $1448/1538 \times 10^{9} = 941{,}5$ Mbit/s.
Para ver como as perdas de eficiência se compõem, vamos declarar um modelo. Suponha que cabeçalhos ocupem $3\%$ da vazão e que, dos bytes restantes destinados a dados, $2\%$ repitam bytes já enviados. A fração de dados novos será
\[G = R \times (1 - 0{,}02) \times (1 - 0{,}03) = 0{,}9506\,R,\]ou $95{,}06\%$ da vazão. A multiplicação vale porque definimos a retransmissão sobre a parcela que restou depois dos cabeçalhos. Se as porcentagens vierem de denominadores diferentes, precisaremos primeiro convertê-las para a mesma fronteira; somá-las ou multiplicá-las sem essa definição produz apenas um número bem formatado.
Chegamos agora ao conceito que faz esta seção existir. Considere um enlace com taxa $R$ e ida e volta $\text{RTT}$. Enquanto o remetente espera a confirmação do primeiro bit, ele poderia estar transmitindo. A quantidade de dados que cabe “em voo” no caminho é o produto banda-atraso, ou BDP, de Bandwidth-Delay Product:
\[\text{BDP} = R \cdot \text{RTT}\]Dimensionalmente, bits por segundo vezes segundos dá bits. O BDP é a quantidade de dados que precisa permanecer não confirmada para que um caminho com capacidade $R$ continue ocupado durante um RTT. Esses bits podem estar em propagação, em transmissão ou em filas ao longo do caminho; a metáfora do cano representa o conjunto, não apenas a fibra.
Para $R = 100$ Mbit/s e $\text{RTT} = 100$ ms,
\[\text{BDP} = 10^{8} \times 0{,}1 = 10^{7}\ \text{bits} = 1{,}25\ \text{MB}\]Um megabyte e um quarto de dados não confirmados. Se o protocolo, o controle de congestionamento, o receptor ou os buffers das pontas impuserem um limite menor, o enlace ficará ocioso enquanto o remetente espera confirmações.
E aqui está o resultado que a esperta leitora deve levar da seção. Em um modelo ideal, um fluxo autorizado a manter no máximo $W$ bits não confirmados tem vazão limitada simultaneamente pela capacidade $R$ e pela janela:
\[R_{\text{efetiva}} \le \min\left(R,\frac{W}{\text{RTT}}\right).\]A janela clássica do TCP, anunciada em um campo de $16$ bits, vale no máximo $65\,535$ bytes, ou $64$ KiB. Sobre o enlace de $100$ Mbit/s com $100$ ms de ida e volta:
\[R_{\text{efetiva}} = \frac{65\,535 \times 8}{0{,}1} = 5\,242\,800\ \text{bit/s} = 5{,}24\ \text{Mbit/s}.\]Cinco vírgula vinte e quatro megabits por segundo em um enlace de cem. Neste exemplo, supomos que a janela anunciada seja a única restrição; perdas, janela de congestionamento e limites da aplicação poderiam reduzir ainda mais a vazão. Sob essa hipótese, a conexão usa apenas $5{,}24\%$ da capacidade porque o campo de janela do TCP possui dezesseis bits. É por isso que existe o escalonamento de janela da RFC 7323, e é o primeiro exemplo desta série de um número de cabeçalho condicionando a arquitetura de um sistema.
O caso simétrico também merece a conta. Para saturar $1$ Gbit/s com $\text{RTT} = 20$ ms, típico de uma conexão entre regiões próximas, é preciso manter em voo
\[\text{BDP} = \frac{10^{9} \times 0{,}02}{8} = 2\,500\,000\ \text{bytes} = 2{,}5\ \text{MB},\]o que exige janela de $2{,}5$ MB, aproximadamente quarenta vezes maior que o máximo sem escalonamento, e exige também buffers de socket compatíveis nas duas pontas. Se o menor limite efetivo for $W<2{,}5$ MB, a fração máxima de uso será $W/\text{BDP}$ antes mesmo de considerarmos perdas. O Artigo 2 mostrará que o TCP ainda impõe outra restrição, a janela de congestionamento, além da janela anunciada pelo receptor.
Fecho a seção com uma comparação que costuma incomodar. Transferir $10$ GB por um enlace de $1$ Gbit/s saturado leva $80$ s. Transportar uma mídia com os mesmos $10$ GB em doze horas porta a porta leva $43\,200$ s, e a rede vence por um fator de $540$. Para inverter a pergunta, precisamos permitir que a capacidade física da remessa cresça: em doze horas, o enlace move $5{,}4$ TB. Uma remessa capaz de carregar mais que isso terá throughput médio superior a $1$ Gbit/s, embora o primeiro byte ainda leve doze horas para chegar. É essa combinação de grande capacidade e enorme latência que sustenta serviços de migração com veículos cheios de dispositivos de armazenamento.
5.1 Exercícios da Seção 5
1. Calcule o produto banda-atraso de um enlace intercontinental
Qual o BDP de um enlace de $100$ Mbit/s com RTT de $100$ ms?
Solução: Aplicando a definição,
\[\text{BDP} = 10^{8}\ \text{bit/s} \times 0{,}1\ \text{s} = 10^{7}\ \text{bits}.\]Convertendo, $10^{7}/8 = 1\,250\,000$ bytes, ou $1{,}25$ MB. Esse é o volume de dados que o caminho comporta em trânsito. A interpretação operacional: para manter o enlace ocupado, o remetente precisa poder ter $1{,}25$ MB não confirmados a qualquer instante. Qualquer limite abaixo disso, venha do protocolo, do sistema operacional ou da aplicação, transforma o enlace em um recurso subutilizado.
2. Determine a vazão de uma janela de 64 KiB
Qual a vazão máxima de uma conexão limitada a uma janela de $64$ KiB, com RTT de $100$ ms? Que fração do enlace de $100$ Mbit/s ela usa?
Solução: A janela máxima sem escalonamento é $65\,535$ bytes, ou $524\,280$ bits. A vazão é
\[R_{\text{efetiva}} = \frac{524\,280}{0{,}1} = 5{,}2428\ \text{Mbit/s},\]correspondente a $5{,}24\%$ do enlace. Aumentar o enlace para $1$ Gbit/s não muda nada: a vazão continua $5{,}24$ Mbit/s, agora usando $0{,}52\%$ da capacidade. Este é o exemplo canônico de um gargalo que se desloca sem que ninguém perceba, e é o motivo pelo qual o primeiro passo de qualquer diagnóstico de vazão baixa é comparar a janela em uso com o BDP, e não olhar o gráfico de utilização do enlace.
3. Dimensione a janela necessária para saturar 1 Gbit/s
Qual janela é necessária para saturar um enlace de $1$ Gbit/s com RTT de $20$ ms?
Solução: A janela precisa cobrir o BDP:
\[W = R \cdot \text{RTT} = 10^{9} \times 0{,}02 = 2 \times 10^{7}\ \text{bits} = 2{,}5\ \text{MB}\]Como $2{,}5$ MB excede em quase quarenta vezes o máximo de $64$ KiB do campo de janela, é obrigatório o escalonamento de janela da RFC 7323, que multiplica o valor anunciado por $2^{s}$, com $s$ entre $0$ e $14$. O menor $s$ que serve satisfaz $65\,535 \times 2^{s} \ge 2\,500\,000$, ou seja $2^{s} \ge 38{,}15$, portanto $s = 6$, que permite anunciar até $4{,}19$ MB. Registre que o escalonamento é negociado apenas no pacote inicial da conexão: se ele não foi acordado ali, não há como habilitá-lo depois, e a conexão inteira viverá com o teto de $64$ KiB.
4. Separe vazão de goodput
Em um modelo no qual cabeçalhos ocupam $3\%$ da vazão e, depois deles, retransmissões ocupam $2\%$ da parcela destinada a dados, qual é o goodput como fração da vazão?
Solução: Pela definição do enunciado, primeiro restam $1-0{,}03=0{,}97$ da vazão depois dos cabeçalhos. Em seguida, $1-0{,}02=0{,}98$ dessa parcela corresponde a dados novos. Logo,
\[G = R \times 0{,}98 \times 0{,}97 = 0{,}9506\,R.\]O goodput é $95{,}06\%$ da vazão. A soma $R(1-0{,}05)=0{,}95R$ erraria por $0{,}06$ ponto percentual porque trataria as duas perdas como frações do mesmo total. Para perdas de $20\%$ e $30\%$ definidas na mesma ordem, a multiplicação daria $0{,}56R$, enquanto a subtração daria $0{,}50R$, diferença de $0{,}06R$ ou $10{,}71\%$ do valor correto. A consequência é mais cuidadosa que uma regra de bolso: compor frações exige declarar seus denominadores.
5. Compare a rede com o transporte físico
Transferir $10$ GB por um enlace de $1$ Gbit/s saturado, ou transportar uma mídia com a mesma quantidade de dados em doze horas: qual vence? Se a capacidade da remessa puder crescer, em que volume seu throughput médio empata com o enlace?
Solução: Pela rede, $T = 10 \times 10^{9} \times 8 / 10^{9} = 80$ s. Pelo avião, $12 \times 3600 = 43\,200$ s. A rede vence por um fator de $43\,200/80 = 540$.
O ponto de inversão é o volume que o enlace consegue mover no mesmo tempo de voo:
\[V^{*} = \frac{10^{9} \times 43\,200}{8} = 5{,}4 \times 10^{12}\ \text{bytes} = 5{,}4\ \text{TB}\]Acima de $5{,}4$ TB por remessa, o transporte físico move mais dados no mesmo intervalo de doze horas. Isso não significa que entregue qualquer byte antes da rede: a latência da remessa continua sendo de doze horas. A comparação demonstra que capacidade média e latência são eixos independentes; tratar rápido como uma única grandeza mistura duas perguntas diferentes.
| Alternativa | Volume | Tempo | Throughput médio |
|---|---|---|---|
| enlace saturado | $10$ GB | $80$ s | $1$ Gbit/s |
| remessa inicial | $10$ GB | $12$ h | $1{,}85$ Mbit/s |
| remessa no empate | $5{,}4$ TB | $12$ h | $1$ Gbit/s |
A tabela torna explícita a troca de regime: para apenas $10$ GB, o enlace vence tanto em latência quanto em vazão; a remessa só empata em vazão quando sua capacidade sobe para $5{,}4$ TB, sem reduzir as doze horas até a entrega.
6. Jitter e a estatística da espera
Se a latência fosse constante, esta seção não existiria. Ela não é. O mesmo par de máquinas, medido cem vezes seguidas, produz cem valores diferentes, e a dispersão desses valores tem nome e consequência.
O jitter é a variação do atraso, e não o atraso. A definição operacional que a série usa é a da RFC 3550, que padroniza o RTP: para pacotes enviados nos instantes $S_i$ e recebidos nos instantes $R_i$, define-se a diferença de espaçamento entre dois pacotes consecutivos como
\[D_i = (R_i - R_{i-1}) - (S_i - S_{i-1})\]e o estimador incremental de jitter como
\[J_i = J_{i-1} + \frac{\vert D_i \vert - J_{i-1}}{16}\]com $J_0 = 0$. A RFC 3550 descreve o ganho $1/16$ como um compromisso entre redução de ruído e velocidade de convergência. Se $\vert D_i \vert$ permanecer constante, a fração da mudança incorporada depois de $n$ atualizações será $1-(15/16)^n$: após $16$ atualizações, o estimador terá percorrido apenas $64{,}4\%$ do caminho; depois de $48$, $95{,}5\%$; e depois de $72$, $99{,}0\%$. Portanto, os primeiros pacotes de um fluxo iniciado com $J_0=0$ produzem uma estimativa transitória menor que o regime.
Vamos aos números. Considere um fluxo de oito pacotes enviados a cada $20$ ms, com os instantes de chegada abaixo, todos em milissegundos:
| $i$ | $S_i$ | $R_i$ | $D_i$ | $J_i$ |
|---|---|---|---|---|
| 0 | 0 | 12 | não se aplica | 0,000 |
| 1 | 20 | 35 | 3 | 0,188 |
| 2 | 40 | 51 | −4 | 0,426 |
| 3 | 60 | 88 | 17 | 1,462 |
| 4 | 80 | 93 | −15 | 2,308 |
| 5 | 100 | 112 | −1 | 2,226 |
| 6 | 120 | 152 | 20 | 3,337 |
| 7 | 140 | 154 | −18 | 4,253 |
Os atrasos individuais foram $12$, $15$, $11$, $28$, $13$, $12$, $32$ e $14$ ms, com desvio padrão amostral de $8{,}11$ ms e amplitude de $21$ ms. O estimador da RFC 3550 devolve $J = 4{,}25$ ms depois de sete atualizações, cerca de metade do desvio padrão. Não é erro do estimador: é o regime transitório do ganho $1/16$ operando como anunciado. Quem lê $J$ nos primeiros segundos de um fluxo está lendo um número que ainda não convergiu.
Agora a parte que muda decisões de produto. Considere dez medições de atraso de ida, em milissegundos:
\[18,\ 21,\ 19,\ 24,\ 20,\ 22,\ 19,\ 140,\ 21,\ 20.\]A média é $32{,}4$ ms e a mediana é $20{,}5$ ms. A média é maior que nove das dez observações. Removendo o valor $140$, a média cai $36{,}9\%$, para $20{,}44$ ms, praticamente igual à mediana, enquanto a mediana cai $2{,}4\%$, para $20$ ms. Um único ponto em dez controla a média e não controla a mediana.
Este é o motivo pelo qual a média, sozinha, é insuficiente para descrever latência. Ela continua útil em identidades como a lei de Little, mas não revela quantas requisições caíram na cauda. Cada usuário experimenta uma realização da distribuição, não sua média abstrata. Para localizar essa experiência, a série usa $p_{50}$, $p_{95}$ e $p_{99}$: em uma distribuição contínua, $p_q$ é o valor abaixo do qual cai a fração $q$ das observações. Em amostras finitas e com empates, o método de quantil precisa ser declarado.
Uma advertência honesta, que a série de Estatística possui em detalhe no artigo sobre percentis e boxplot: com dez observações, o $p_{95}$ depende fortemente do método de interpolação. Ordenando a amostra acima, obtemos $18, 19, 19, 20, 20, 21, 21, 22, 24, 140$. Pelo método linear usado na Seção 8, o $p_{95}$ cai entre o nono e o décimo valores e vale $87{,}8$ ms; pelo vizinho mais próximo, vale $140$ ms. Ambos obedecem a seus contratos, mas nenhum sustenta uma conclusão estável sobre a cauda. Como regra mínima de contagem, observar dez valores além de $p_{99}$ exige cerca de mil amostras, e observar dez além de $p_{99{,}9}$ exige cerca de dez mil. Isso não garante precisão; apenas evita estimar a cauda a partir de um ou dois pontos.
Feita a ressalva, o efeito de produto continua concreto. Suponha que um serviço processe $2000$ requisições por minuto e que $1\%$ delas pertença a uma classe lenta acima de $900$ ms. Isso produz $20$ requisições lentas por minuto e $28\,800$ por dia. O número conta requisições, não pessoas; para convertê-lo em usuários afetados, precisamos saber quantas requisições cada pessoa faz e como os eventos lentos se distribuem entre elas. Tampouco podemos deduzir a média apenas de $p_{50}$ e $p_{99}$. Se construirmos um exemplo artificial com $99\%$ das respostas em $20$ ms e $1\%$ exatamente em $900$ ms, a média será $28{,}8$ ms, mas essa distribuição é uma hipótese adicional, não uma consequência dos percentis.
A situação se torna mais importante quando várias chamadas participam da mesma resposta, pois suas caudas se compõem. Considere uma página que dispara $30$ requisições em paralelo e só termina quando a última responde. Se as requisições forem independentes e cada uma tiver $1\%$ de chance de exceder $900$ ms, a probabilidade de a página encontrar pelo menos uma chamada lenta será
\[P(\text{ao menos uma lenta}) = 1 - (1 - 0{,}01)^{30} = 1 - 0{,}99^{30} = 0{,}2603 = 26{,}03\%.\]O resultado, $26{,}03\%$, mostra a amplificação produzida pelo fan-out. Sob a hipótese de independência, uma classe lenta que atinge $1\%$ das chamadas de um componente atinge pouco mais de um quarto das páginas que esperam por trinta chamadas. Em linguagem aproximada, o limiar antes excedido apenas na cauda de $1\%$ do componente passa a ser excedido com frequência muito maior pela página. Não convém chamar esse limiar de $p_{74}$ sem conhecer a distribuição completa da página, pois um percentil é um valor da distribuição, não apenas uma probabilidade isolada de excedência. Ainda assim, a conta explica por que a cauda é central em qualquer sistema com fan-out. Ela reaparece no Artigo 10, quando um balanceador distribuir requisições, e no Artigo 12, quando uma cadeia de microsserviços somar os atrasos de cada salto.
Vale registrar o que o jitter faz com aplicações interativas. Voz e vídeo em tempo real atrasam a reprodução para absorver variações de chegada. Se o prazo de reprodução de cada pacote for definido como o instante de envio mais um deslocamento $B$, um pacote com atraso de rede maior que $B$ chegará tarde. Aumentar $B$ reduz a fração tardia, mas acrescenta atraso de reprodução a todos os pacotes. O ponto adequado depende da distribuição dos atrasos e do relógio de referência; um buffer de $50$ ms não tolera qualquer atraso de $50$ ms sem que antes definamos a partir de qual linha de base esses $50$ ms são contados.
Este é o momento de a leitora abrir o Laboratório 01 da suíte NetworkLabs e transformar essa distinção em um experimento controlado. No modo guiado, a rota, a largura de banda, a carga útil, o prazo de reprodução e a amostra de mil pacotes permanecem fixos; por isso, a única variável disponível é a amplitude máxima da perturbação injetada. Ao carregar, o laboratório fixa automaticamente a execução com amplitude zero como referência. Desloque então o controle até $50$ ms: as métricas e o histograma responderão durante o movimento, sem exigir uma nova execução, enquanto o globo acompanhará o trecho seguinte da rota. Como o laboratório gera perturbações centradas em pares opostos, a média da amostra permanece no atraso-base por construção. Contudo, a distribuição se alarga, os percentis superiores e o estimador da RFC 3550 crescem, e parte das chegadas atravessa o prazo $B$. Se quiser iniciar outra comparação, fixe os resultados exibidos como a nova referência.
Essa comparação não mede a Internet nem afirma que atrasos reais sejam simétricos. Ela isola uma causa para que a consequência se torne visível: embora a média permaneça constante, a cauda passa a produzir pacotes tardios. O laboratório também separa a amplitude que injetamos do jitter que medimos, evitando que um parâmetro da simulação seja confundido com o estimador definido no início desta seção.
6.1 Exercícios da Seção 6
1. Calcule média, mediana e desvio de uma amostra com cauda
Para os dez atrasos $18, 21, 19, 24, 20, 22, 19, 140, 21, 20$ ms, calcule média, mediana e desvio padrão amostral, e compare com os valores obtidos ao remover a maior observação.
Solução: A soma das dez observações é $324$, portanto a média é $32{,}4$ ms. Ordenando, $18, 19, 19, 20, 20, 21, 21, 22, 24, 140$; com $n$ par, a mediana é a média dos dois valores centrais, $(20 + 21)/2 = 20{,}5$ ms. O desvio padrão amostral é $37{,}85$ ms.
Removendo o $140$, a soma cai para $184$ em nove observações, dando média $20{,}44$ ms e mediana $20$ ms.
| Estatística | Com o valor 140 | Sem o valor 140 | Variação |
|---|---|---|---|
| média | $32{,}40$ ms | $20{,}44$ ms | $-36{,}9\%$ |
| mediana | $20{,}50$ ms | $20{,}00$ ms | $-2{,}4\%$ |
| desvio padrão | $37{,}85$ ms | $1{,}81$ ms | $-95{,}2\%$ |
Uma observação em dez altera fortemente a média e o desvio, mas quase não move a mediana. Isso não torna a média errada: ela responde a perguntas como consumo médio de recursos e, pela lei de Little, concorrência média. Entretanto, se o objetivo for descrever a experiência típica e a cauda, a média isolada não basta. Por isso, o relatório deve combiná-la com mediana, percentis altos, tamanho da amostra e método de quantil.
2. Aplique o estimador de jitter da RFC 3550
Para o fluxo de oito pacotes da tabela desta seção, reconstrua os valores de $D_i$ e $J_i$.
Solução: Os pacotes são enviados a cada $20$ ms, portanto $S_i - S_{i-1} = 20$ para todo $i$. Com os instantes de chegada $12, 35, 51, 88, 93, 112, 152, 154$:
| $i$ | $R_i - R_{i-1}$ | $D_i$ | $|D_i|$ | $J_i = J_{i-1} + (|D_i| - J_{i-1})/16$ |
|---|---|---|---|---|
| 1 | 23 | 3 | 3 | $0 + (3-0)/16 = 0{,}188$ |
| 2 | 16 | −4 | 4 | $0{,}188 + (4-0{,}188)/16 = 0{,}426$ |
| 3 | 37 | 17 | 17 | $0{,}426 + (17-0{,}426)/16 = 1{,}462$ |
| 4 | 5 | −15 | 15 | $1{,}462 + (15-1{,}462)/16 = 2{,}308$ |
| 5 | 19 | −1 | 1 | $2{,}308 + (1-2{,}308)/16 = 2{,}226$ |
| 6 | 40 | 20 | 20 | $2{,}226 + (20-2{,}226)/16 = 3{,}337$ |
| 7 | 2 | −18 | 18 | $3{,}337 + (18-3{,}337)/16 = 4{,}253$ |
O valor final é $J = 4{,}25$ ms. Repare na linha $5$: um $\vert D_i \vert$ pequeno faz o estimador cair, porque a média móvel puxa na direção da nova observação. Portanto, o estimador acompanha a dispersão recente em vez de acumular indefinidamente todos os eventos anteriores. Essa adaptação é útil para controle de reprodução, mas não substitui o registro das observações brutas em uma análise de incidente, na qual um pico antigo ainda pode ser relevante.
3. Traduza um percentil em número de requisições
Um serviço processa $2000$ requisições por minuto, e $1\%$ delas pertence a uma classe lenta acima de $900$ ms. Quantas requisições lentas ocorrem por dia? É possível converter esse resultado em número de pessoas apenas com esses dados?
Solução: Em um minuto, $2000 \times 0{,}01 = 20$ requisições pertencem à classe lenta. Em um dia,
\[20 \times 60 \times 24 = 28\,800\ \text{requisições}.\]O resultado é $28\,800$ requisições, não necessariamente $28\,800$ pessoas. Uma pessoa pode emitir várias chamadas e sofrer mais de um evento lento; além disso, os eventos podem se concentrar em determinados usuários, regiões ou sessões. Para contar pessoas afetadas, precisamos de identificadores por usuário ou sessão e da distribuição conjunta dos eventos. Pelo mesmo motivo, $p_{50}$ e a fração acima de $900$ ms não determinam a média: os valores entre esses pontos continuam desconhecidos.
4. Componha as caudas de requisições paralelas
Uma página dispara $30$ requisições em paralelo e só termina quando a última responde. Se cada requisição tem $1\%$ de chance independente de exceder $900$ ms, qual a probabilidade de a página exceder?
Solução: A página não excede apenas se nenhuma das trinta exceder. Sob independência,
\[P(\text{nenhuma lenta}) = (1 - 0{,}01)^{30} = 0{,}99^{30} = 0{,}7397,\]logo
\[P(\text{ao menos uma lenta}) = 1 - 0{,}7397 = 0{,}2603 = 26{,}03\%.\]Sob independência, o limiar de $900$ ms passa de $1\%$ de excedência por componente para $26{,}03\%$ por página. A conta não deve ser extrapolada para chamadas correlacionadas sem medir a dependência. Com correlação positiva perfeita, por exemplo, as trinta chamadas seriam lentas juntas em $1\%$ das páginas, e a probabilidade de ao menos uma lenta cairia de $26{,}03\%$ para $1\%$; em outros padrões de dependência, o resultado muda de outra forma. Filas, pools de conexão e pausas de coletor de lixo criam causas compartilhadas, mas a direção e a intensidade do efeito sobre a página dependem da distribuição conjunta. Assim, reduzir o fan-out diminui as oportunidades de uma chamada independente atrasar a conclusão, enquanto a análise de causas compartilhadas exige telemetria por requisição.
5. Dimensione um buffer de reprodução
Para a mesma amostra de dez atrasos, calcule a fração de pacotes que chegaria tarde demais com um buffer de reprodução de $30$ ms, e o efeito de aumentá-lo para $100$ ms.
Solução: Adotaremos como prazo de reprodução o instante de envio mais $B$. Nesse modelo simplificado, um atraso de rede maior que $B$ produz um pacote tardio. Ordenando os atrasos, $18, 19, 19, 20, 20, 21, 21, 22, 24, 140$:
| $B$ | Pacotes tardios | Fração | Atraso adicional imposto a todos |
|---|---|---|---|
| $30$ ms | 1 (o de 140) | $10\%$ | $30$ ms |
| $100$ ms | 1 (o de 140) | $10\%$ | $100$ ms |
| $150$ ms | 0 | $0\%$ | $150$ ms |
Aumentar de $30$ para $100$ ms não melhorou nada e piorou a interatividade de todos os pacotes em $70$ ms. Só a $150$ ms a perda zera, ao custo de um atraso fixo cinco vezes maior que a mediana da rede. É o compromisso puro: o buffer é dimensionado pela cauda e cobrado de todo mundo. Note também que a amostra tem dez pontos, portanto a fração de $10\%$ carrega a mesma fragilidade dos percentis discutida no texto; com mil pacotes, a decisão seria tomada sobre o $p_{99}$ observado, e não sobre um único valor extremo.
7. Filas: o mecanismo que transforma carga em latência
Até aqui, três parcelas vieram da geometria, do tamanho dos dados e do trabalho dos equipamentos. Falta explicar a quarta: o tempo de fila. Essa parcela separa uma rede que funciona em condições leves de uma rede que continua responsiva sob carga, porque depende do comportamento dos demais fluxos e não pode ser obtida apenas da folha de dados do equipamento.
Um enlace de saída é um servidor com uma fila. Pacotes chegam a uma taxa média $\lambda$ e são transmitidos a uma taxa média $\mu$, ambas em pacotes por segundo. A utilização é a razão
\[\rho = \frac{\lambda}{\mu}\]adimensional, e representa a fração do tempo em que o enlace está ocupado. Para $\rho \ge 1$ a fila cresce sem limite e o sistema é instável; toda a discussão que segue supõe $\rho \lt 1$.
O modelo mais simples que captura o essencial é a fila M/M/1: chegadas segundo um processo de Poisson, tempos de serviço exponenciais, um único servidor e disciplina de atendimento por ordem de chegada. Ele não descreve todo tráfego real, mas oferece um ponto de partida cujas hipóteses podem ser verificadas. Em modelos mais gerais, a espera muda com a variabilidade combinada das chegadas e do serviço; por isso, não devemos presumir de antemão que M/M/1 sempre erra na mesma direção. Para M/M/1, o tempo médio total no sistema, incluindo fila e serviço, é
\[W = \frac{1}{\mu - \lambda} = \frac{1}{\mu(1 - \rho)},\]enquanto o tempo médio gasto apenas na fila é
\[W_q = W - \frac{1}{\mu} = \frac{\rho}{\mu - \lambda} = \frac{\rho}{\mu(1-\rho)}.\]Consequentemente, o número médio de pacotes no sistema e o número médio esperando na fila são, respectivamente,
\[L = \lambda W = \frac{\rho}{1 - \rho}, \qquad L_q = \lambda W_q = \frac{\rho^2}{1 - \rho}.\]Essa distinção evita um erro frequente: $W$ inclui o tempo de serviço de $1/\mu$, enquanto $W_q$ mede somente a espera anterior ao serviço. Em ambas as expressões, o denominador $1-\rho$ explica o crescimento acelerado perto da saturação. Com $\mu = 1000$ pacotes/s, cada serviço leva em média $1$ ms, e a Tabela 3 mostra o que acontece quando a carga sobe.
| $\lambda$ (pacotes/s) | $\rho$ | $W_q$ (ms) | $W$ (ms) | $L$ (pacotes) |
|---|---|---|---|---|
| 500 | 0,50 | 1,0 | 2,0 | 1,0 |
| 800 | 0,80 | 4,0 | 5,0 | 4,0 |
| 900 | 0,90 | 9,0 | 10,0 | 9,0 |
| 950 | 0,95 | 19,0 | 20,0 | 19,0 |
| 990 | 0,99 | 99,0 | 100,0 | 99,0 |
Tabela 3: espera média na fila, tempo médio total e ocupação média de uma fila M/M/1 com $\mu = 1000$ pacotes/s.
Leia a tabela duas vezes. Da primeira para a última linha, a taxa de chegada quase dobrou, de $500$ para $990$, mas a espera $W_q$ se multiplicou por noventa e nove e o tempo total $W$, por cinquenta. Entre $\rho = 0{,}9$ e $\rho = 0{,}95$, um aumento relativo de carga de $5{,}6\%$ elevou $W_q$ de $9$ para $19$ ms. A relação não é linear nem quadrática: é hiperbólica, com assíntota vertical em $\rho=1$.
A Figura 4 mostra a curva, e vale olhá-la por um instante antes de continuar.
Figura 4: no modelo M/M/1 com serviço médio de $1$ ms, o tempo total $W$ cresce de $2$ para $20$ ms quando a utilização passa de $0{,}5$ para $0{,}95$. A inclinação crescente, e não um limiar universal, é o resultado que orienta o dimensionamento.
A consequência de engenharia precisa ser formulada como um orçamento, não como uma regra fixa de utilização. Neste exemplo M/M/1, se o requisito for manter o tempo total médio em no máximo $5$ ms com $\mu=1000$ pacotes/s, resolvemos
\[\frac{1}{1000 - \lambda} \le 0{,}005 \quad\Longrightarrow\quad \lambda \le 800\]ou seja, $\rho\le0{,}8$. Nesse modelo e para esse orçamento, reservar $20\%$ da taxa de serviço limita $W$ a $5$ ms. Outro processo de chegadas, outra distribuição de serviço ou outro objetivo produzirá um limite diferente. Portanto, uma linha de alerta em $80\%$ só tem justificativa quando deriva de hipóteses e de um orçamento semelhantes; não existe um valor universal que sirva para todo enlace.
Há um segundo resultado, mais geral e mais bonito, que se aplica a qualquer sistema estável, sem hipótese nenhuma sobre a distribuição de chegadas ou serviços. É a lei de Little:
\[L = \lambda W,\]na qual $L$ é o número médio de itens no sistema, $\lambda$ é a taxa média de chegada e $W$ é o tempo médio que um item passa no sistema. A generalidade é o que a torna útil: ela vale para pacotes em um roteador, requisições em um servidor, pedidos em uma fábrica e pessoas em uma fila de banco.
A utilidade da lei aparece imediatamente no dimensionamento de serviços. Se um serviço atende $2000$ requisições por segundo com tempo médio de resposta de $50$ ms, então há, em média,
\[L = 2000 \times 0{,}05 = 100\]requisições simultaneamente dentro da fronteira medida. Esse número ajuda a dimensionar limites de concorrência. Para convertê-lo diretamente em conexões ou threads, porém, precisamos acrescentar a hipótese de que cada requisição mantém exatamente um desses recursos durante todo o tempo $W$. Se essa hipótese valer, um pool de vinte conexões não sustenta $2000$ requisições por segundo com $50$ ms de ocupação por conexão: forma-se uma fila antes do recurso. Se houver multiplexação, processamento assíncrono ou liberação antecipada, a relação precisa ser refeita para o tempo durante o qual cada recurso permanece retido. A lei de Little reaparece no Artigo 10, para dimensionar instâncias, e no Artigo 24, para planejar capacidade.
Fecho com a patologia que resume a seção. Memória ficou barata, e a reação natural de quem projeta equipamento de rede foi colocar buffers generosos, para não descartar pacotes. O resultado é o bufferbloat. Considere um enlace de $10$ Mbit/s com um buffer de $256$ MB completamente ocupado. O tempo para drenar esse buffer é
\[T_{\text{fila}} = \frac{256 \times 10^{6} \times 8}{10 \times 10^{6}} = 204{,}8\ \text{s}.\]O resultado é $204{,}8$ s, mais de três minutos de fila para um pacote colocado atrás de todo esse volume na mesma direção. O TCP percebe congestionamento por perdas e pela evolução das confirmações e do RTT; um buffer excessivo pode adiar perdas e inflar o RTT, fazendo o remetente reagir a um sinal muito tardio. Uma confirmação percorre o sentido inverso e só sofre a mesma fila se também houver gargalo naquele sentido, razão pela qual não devemos imaginar um único pacote de controle universalmente preso atrás dos dados. Ainda assim, para tráfego interativo que compartilha a fila de saída, o atraso pode equivaler a uma falha. O buffer grande trocou descarte antecipado por uma fila potencialmente enorme, sem garantir uma experiência melhor.
Este é o momento de manipular os números em vez de lê-los. O laboratório abaixo compõe as quatro parcelas da Seção 3 com a fila desta seção, e mostra o orçamento inteiro de uma página se rearranjar conforme a leitora muda distância, taxa do enlace, tamanho do objeto, utilização, número de saltos e número de requisições.
Duas escolhas de modelagem precisam ser declaradas, porque elas determinam o que a leitora vai ver. A parcela de fila reúne dois efeitos distintos e ambos reais: a espera do primeiro pacote no gargalo, que vale $\rho/(1-\rho)$ vezes o tempo de serviço de um quadro cheio, e a disputa durante a transferência, porque um enlace ocupado a $\rho$ entrega ao fluxo apenas $(1-\rho)R$. A parcela de transmissão continua sendo o $L/R$ puro, para que fique visível o que é física do enlace e o que é competição com terceiros. A segunda escolha está no cálculo da página: ao paralelizar $n$ requisições, a latência é paga uma vez e a transmissão é paga $n$ vezes, porque os objetos disputam o mesmo enlace. Latência paraleliza; largura de banda não.
Vale começar pelos presets, que reproduzem as rotas da Tabela 2, e depois empurrar a utilização de $0{,}50$ para $0{,}95$ sem tocar em mais nada. Na rota São Paulo–Virgínia com objetos de $256$ KiB, a fila salta de $17{,}8\%$ para $80{,}5\%$ do atraso de cada requisição, e o total de uma página com oito objetos em paralelo passa de $413$ ms para $3437$ ms. Nenhum equipamento foi trocado, nenhum código foi alterado e nenhuma distância mudou.
7.1 Exercícios da Seção 7
1. Calcule espera, tempo total e ocupação para três cargas
Para uma fila M/M/1 com $\mu = 1000$ pacotes/s, calcule $\rho$, $W_q$, $W$ e $L$ para $\lambda \in {500, 900, 990}$.
Solução: Aplicando $\rho=\lambda/\mu$, $W_q=\rho/(\mu-\lambda)$, $W=1/(\mu-\lambda)$ e $L=\rho/(1-\rho)$:
| $\lambda$ | $\rho$ | $W_q$ | $W$ | $L$ |
|---|---|---|---|---|
| 500 | $0{,}50$ | $1{,}0$ ms | $2{,}0$ ms | $1{,}0$ |
| 900 | $0{,}90$ | $9{,}0$ ms | $10{,}0$ ms | $9{,}0$ |
| 990 | $0{,}99$ | $99{,}0$ ms | $100{,}0$ ms | $99{,}0$ |
Entre a primeira e a terceira linha, $\lambda$ cresceu $98\%$ e $W$ cresceu $4900\%$. Verifique também que a lei de Little é respeitada em cada linha: $L = \lambda W$ dá $500 \times 0{,}002 = 1$, $900 \times 0{,}010 = 9$ e $990 \times 0{,}100 = 99$. A consistência não é coincidência: a fórmula de $L$ para M/M/1 é derivada de forma que Little valha, como tem de valer para qualquer sistema estável.
2. Determine a utilização máxima que respeita um orçamento de tempo total
Com $\mu = 1000$ pacotes/s, qual a maior taxa de chegada que mantém o tempo médio total $W$ em no máximo $5$ ms?
Solução: Impondo $W \le 0{,}005$ s,
\[\frac{1}{1000 - \lambda} \le 0{,}005 \quad\Longrightarrow\quad 1000 - \lambda \ge 200 \quad\Longrightarrow\quad \lambda \le 800.\]A utilização máxima deste modelo é $\rho=0{,}8$. Se a taxa de serviço também puder ser expressa em bits por segundo porque os pacotes têm tamanho constante, a mesma fração corresponderá a $80\%$ da capacidade em bits por segundo. Com tamanhos variáveis, porém, não podemos converter diretamente $800$ pacotes/s em $800$ Mbit/s. Um orçamento mais rigoroso, $W\le2$ ms, exigiria $\lambda\le500$ pacotes/s, ou metade da taxa de serviço assumida. Assim, o orçamento de latência se transforma em reserva de capacidade somente depois que as unidades e o modelo de tráfego são alinhados.
| Orçamento de $W$ | $\lambda_{\max}$ | $\rho_{\max}$ |
|---|---|---|
| $5$ ms | $800$ pacotes/s | $0{,}80$ |
| $2$ ms | $500$ pacotes/s | $0{,}50$ |
Portanto, reduzir o orçamento de $5$ para $2$ ms não corta a utilização admissível na mesma proporção: a forma hiperbólica da curva força uma reserva adicional de capacidade.
3. Aplique a lei de Little ao dimensionamento de um pool
Um serviço atende $2000$ requisições por segundo com tempo médio de resposta de $50$ ms. Quantas requisições estão, em média, dentro da fronteira medida? Supondo que cada uma retenha uma conexão durante os $50$ ms completos e que não haja multiplexação, qual o efeito de um pool de $20$ conexões?
Solução: Pela lei de Little,
\[L = \lambda W = 2000 \times 0{,}05 = 100\ \text{requisições simultâneas}.\]Sob as hipóteses do enunciado, o pool permite no máximo vinte requisições em serviço ao mesmo tempo. Invertendo Little para descobrir a vazão sustentável nessa restrição,
\[\lambda_{\max} = \frac{L}{W} = \frac{20}{0{,}05} = 400\ \text{requisições/s}.\]Se a demanda continuar em $2000$ requisições/s, a diferença entre chegadas e partidas acumula-se em uma fila antes do pool enquanto não houver rejeição, controle de admissão ou redução da demanda. O tempo observado pelo cliente cresce, embora o tempo de ocupação medido depois da aquisição da conexão permaneça em $50$ ms. Por isso, a fronteira da instrumentação precisa incluir a espera pelo recurso. Com HTTP/2 multiplexado, várias requisições podem compartilhar uma conexão e esta conta deixa de representar o limite correto.
4. Quantifique o bufferbloat
Um enlace de $10$ Mbit/s tem um buffer de saída de $256$ MB. Qual o atraso de fila quando ele está cheio? E com um buffer de $64$ MB?
Solução: O tempo de drenagem é o volume dividido pela taxa:
\[T_{256} = \frac{256 \times 10^{6} \times 8}{10^{7}} = 204{,}8\ \text{s}, \qquad T_{64} = \frac{64 \times 10^{6} \times 8}{10^{7}} = 51{,}2\ \text{s}.\]Reduzir o buffer por quatro reduz por quatro esse limite de atraso, mas ambos os resultados continuam impraticáveis para tráfego interativo. Um pacote colocado atrás de $64$ MB no mesmo sentido espera até $51{,}2$ s. Além disso, um buffer enorme tende a adiar descartes e a inflar o RTT observado pelo TCP. Disciplinas de gerenciamento ativo de filas, como CoDel e FQ-CoDel, procuram limitar o tempo de permanência na fila e fornecer sinais de congestionamento antes que o atraso se torne excessivo.
5. Explique por que a rajada piora a estimativa de M/M/1
O modelo M/M/1 supõe chegadas de Poisson e serviço exponencial. Se as chegadas observadas tiverem coeficiente de variação maior que um, mantendo as demais hipóteses comparáveis, em que direção a aproximação de Kingman indica que a espera se moverá? Por quê?
Solução: A espera em uma fila com um servidor cresce com a variabilidade dos intervalos entre chegadas e dos tempos de serviço. A fórmula de Pollaczek–Khinchine para filas M/G/1 torna isso explícito: a espera é proporcional a $1 + c_s^{2}$, na qual $c_s$ é o coeficiente de variação do tempo de serviço. Para o caso exponencial, $c_s = 1$ e o fator vale $2$; para serviço determinístico, $c_s = 0$ e o fator vale $1$, ou seja, metade da espera; para serviço com cauda pesada, $c_s > 1$ e a espera é maior.
Para chegadas, a aproximação de Kingman para filas G/G/1 mostra que a espera é proporcional a $(c_a^{2}+c_s^{2})/2$, com $c_a$ representando o coeficiente de variação dos intervalos entre chegadas. No modelo M/M/1, $c_a=c_s=1$, e esse fator vale um. Se mantivermos $c_s=1$ e observarmos $c_a>1$, o fator fica maior que um; portanto, a aproximação prevê espera superior à referência M/M/1 na mesma utilização. Se a combinação $(c_a^2+c_s^2)/2$ ficar abaixo de um, a conclusão se inverte. A moral prática é usar M/M/1 para entender a forma da curva sob hipóteses explícitas, e não como garantia universal nem como estimador de $p_{99}$. Prometer um percentil exige medir a distribuição, assunto da próxima seção.
| Variabilidade em relação a M/M/1 | Fator de Kingman | Tendência de $W_q$ |
|---|---|---|
| $c_a=c_s=1$ | $1$ | referência |
| $(c_a^2+c_s^2)/2>1$ | maior que $1$ | acima da referência |
| $(c_a^2+c_s^2)/2<1$ | menor que $1$ | abaixo da referência |
Logo, a rajada piora a estimativa somente quando eleva o fator de variabilidade acima da referência. Sem medir $c_a$ e $c_s$, afirmar que M/M/1 sempre subestima ou sempre superestima a espera seria trocar uma hipótese por uma conclusão.
8. Medindo o que se afirma, em C++23
Nada nas seções anteriores vale se a leitora não conseguir medir. E medir latência é mais fácil de fazer errado do que parece: relógio errado, sem aquecimento, média em vez de percentil, uma repetição só, e o resultado é um número bonito que não descreve nada.
Quatro regras de metodologia, cada uma corrigindo um erro comum.
Primeira, relógio monotônico. Use std::chrono::steady_clock, nunca system_clock. O relógio de sistema pode andar para trás quando o serviço de sincronização de horário o ajusta, e a leitora vai obter durações negativas em algum momento entre a meia-noite e o incidente.
Segunda, aquecimento descartado. As primeiras execuções pagam falhas de cache, alocação de páginas e ajuste de frequência do processador. Descarte-as explicitamente.
Terceira, repetições cronometradas individualmente. Medir mil repetições em bloco e dividir por mil conserva apenas a média e apaga a distribuição. Guarde cada amostra para poder calcular tanto a tendência central quanto a cauda.
Quarta, percentis junto da média. A média continua útil para custo agregado, mas a mediana e os percentis altos descrevem regiões que ela não revela. Para calculá-los, não é preciso ordenar o vetor inteiro: std::nth_element posiciona o elemento de ordem desejada com complexidade linear média, o que importa quando as amostras são milhões.
O programa abaixo implementa as quatro regras para uma operação local. Além disso, calcula percentis por interpolação linear e reproduz o estimador de jitter da RFC 3550 sobre os dados da Seção 6, para que a leitora possa conferir a saída contra os números do texto. Ele não mede a rede por conta própria: para isso, seria necessário acrescentar uma fonte de amostras de envio e chegada, bem como definir o ponto de observação e sincronizar os relógios quando as marcas de tempo viessem de máquinas diferentes.
// latencia.cpp: latency statistics and the RFC 3550 jitter estimator.
// MSVC: cl /std:c++23preview /permissive- /Zc:__cplusplus /W4 /EHsc /O2 latencia.cpp
// Clang: clang++ -std=c++23 -stdlib=libc++ -O2 -Wall -Wextra latencia.cpp -o latencia
#include <algorithm>
#include <chrono>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <expected>
#include <print>
#include <span>
#include <string_view>
#include <vector>
namespace rede {
enum class Erro { amostra_vazia, percentil_invalido, tamanhos_incompativeis };
constexpr std::string_view descrever(Erro e) {
switch (e) {
case Erro::amostra_vazia: return "amostra vazia";
case Erro::percentil_invalido: return "percentil fora de [0, 1]";
case Erro::tamanhos_incompativeis: return "sequencias com tamanhos diferentes";
}
return "erro desconhecido";
}
// Linear interpolation between adjacent order statistics. The vector is copied
// because nth_element reorders its range; a query must not mutate caller data.
std::expected<double, Erro> percentil(std::vector<double> amostras, double p) {
if (amostras.empty()) return std::unexpected(Erro::amostra_vazia);
if (p < 0.0 || p > 1.0) return std::unexpected(Erro::percentil_invalido);
if (p == 0.0) return *std::ranges::min_element(amostras);
if (p == 1.0) return *std::ranges::max_element(amostras);
const double k = (static_cast<double>(amostras.size()) - 1.0) * p;
const auto i = static_cast<std::size_t>(std::floor(k));
const double f = k - static_cast<double>(i);
auto pos = amostras.begin() + static_cast<std::ptrdiff_t>(i);
std::nth_element(amostras.begin(), pos, amostras.end());
const double baixo = *pos;
if (f == 0.0) return baixo;
const double alto = *std::ranges::min_element(std::span(pos + 1, amostras.end()));
return baixo + f * (alto - baixo);
}
// Incremental RFC 3550 jitter estimator, Appendix A.8:
// J <- J + (|D| - J) / 16, where D = (R_i - R_{i-1}) - (S_i - S_{i-1}).
std::expected<double, Erro> jitter_rfc3550(
std::span<const double> envio, std::span<const double> chegada) {
if (envio.size() != chegada.size()) {
return std::unexpected(Erro::tamanhos_incompativeis);
}
double J = 0.0;
for (std::size_t i = 1; i < envio.size(); ++i) {
const double D = (chegada[i] - chegada[i - 1]) - (envio[i] - envio[i - 1]);
J += (std::abs(D) - J) / 16.0;
}
return J;
}
// Discard warm-up runs and time each repetition with a monotonic clock.
template <class Operacao>
std::vector<double> medir(
Operacao&& op, std::size_t aquecimento, std::size_t repeticoes) {
for (std::size_t i = 0; i < aquecimento; ++i) op();
std::vector<double> amostras;
amostras.reserve(repeticoes);
for (std::size_t i = 0; i < repeticoes; ++i) {
const auto t0 = std::chrono::steady_clock::now();
op();
const auto t1 = std::chrono::steady_clock::now();
amostras.push_back(std::chrono::duration<double, std::milli>(t1 - t0).count());
}
return amostras;
}
} // namespace rede
int main() {
// The ten one-way delays from Section 6, in milliseconds.
const std::vector<double> atrasos =
{18.0, 21.0, 19.0, 24.0, 20.0, 22.0, 19.0, 140.0, 21.0, 20.0};
std::println("n = {} amostras", atrasos.size());
for (const double p : {0.50, 0.90, 0.95, 0.99}) {
const auto v = rede::percentil(atrasos, p);
if (v) std::println("p{:02.0f} = {:.2f} ms", p * 100, *v);
else std::println("p{:02.0f} = {}", p * 100, rede::descrever(v.error()));
}
// The eight-packet flow from Section 6, sent every 20 ms.
const std::vector<double> envio = {0, 20, 40, 60, 80, 100, 120, 140};
const std::vector<double> chegada = {12, 35, 51, 88, 93, 112, 152, 154};
const auto jitter = rede::jitter_rfc3550(envio, chegada);
if (jitter) std::println("jitter = {:.2f} ms", *jitter);
else std::println("jitter = {}", rede::descrever(jitter.error()));
// The type forces callers to handle this deliberately triggered error path.
const auto vazio = rede::percentil({}, 0.5);
std::println("amostra vazia: {}",
vazio ? "aceita" : rede::descrever(vazio.error()));
// Apply the same timing machinery to a local operation with an observed result.
std::uint64_t acumulador = 1;
const auto medidas = rede::medir(
[&] {
for (int i = 0; i < 100000; ++i) {
acumulador = acumulador * 1664525U + 1013904223U;
}
},
10, 200);
std::println("op p50 = {:.2f} ms", rede::percentil(medidas, 0.50).value_or(0.0));
std::println("op p99 = {:.2f} ms", rede::percentil(medidas, 0.99).value_or(0.0));
std::println("checksum = {}", acumulador);
return 0;
}
n = 10 amostras
p50 = 20.50 ms
p90 = 35.60 ms
p95 = 87.80 ms
p99 = 129.56 ms
jitter = 4.25 ms
amostra vazia: amostra vazia
Os valores conferem com a Seção 6, incluindo o $p_{95}$ de $87{,}80$ ms que ali serviu para mostrar a fragilidade de percentis altos em amostras pequenas. As três últimas linhas, omitidas porque dependem da máquina, contêm os dois percentis da operação local e o checksum que torna seu resultado observável.
Três observações sobre o código, porque nele há decisões e não apenas sintaxe.
A função percentil devolve std::expected<double, Erro> porque há duas formas legítimas de ela não ter resposta: amostra vazia e percentil fora do intervalo. Um valor sentinela, como NaN, obrigaria o chamador a lembrar de testá-lo; o tipo obriga. O programa exercita o caso degenerado de propósito, e a linha amostra vazia: amostra vazia da saída é a prova de que o caminho de erro existe e funciona.
Ela recebe o vetor por valor, e isso também é deliberado: std::nth_element reordena o intervalo, e uma função de consulta que modifica silenciosamente o argumento do chamador é uma armadilha. A cópia custa uma alocação; a alternativa custa uma tarde de depuração.
A função jitter_rfc3550 recebe std::span<const double>, e não const std::vector<double>&, porque span aceita vetor, arranjo nativo, std::array e qualquer bloco contíguo, sem forçar o chamador a converter. Como as marcas de envio e chegada formam pares, a função rejeita sequências de tamanhos diferentes em vez de truncar silenciosamente a maior.
O acumulador da medição é usado no checksum final, o que torna o resultado observável e impede a eliminação completa do cálculo como código morto. Isso ainda não transforma o exemplo em um benchmark de microarquitetura: otimizações, frequência, afinidade, carga concorrente e resolução do relógio continuam afetando o número. A função serve para demonstrar coleta individual e redução estatística, não para comparar processadores.
A leitora que quiser levar isso adiante tem um exercício aberto e útil: substituir os dados embutidos por medições reais, obtidas com envio de pacotes a um destino escolhido, e comparar os percentis observados com o piso físico da Tabela 2. O Artigo 8 vai formalizar a coleta, a redução e a anonimização desses dados, que é o que separa uma medição de um vazamento.
9. O que delegar à máquina e como conferir
Chegamos à seção que se repete em todos os dezesseis artigos, sempre com a mesma estrutura e sempre com conteúdo específico do assunto.
O que um modelo de linguagem faz bem aqui. Converter um orçamento de latência descrito em prosa em uma tabela de somandos, com as unidades acertadas; gerar o esqueleto de um teste de carga a partir da descrição de um cenário; explicar o que uma métrica exibida em um painel significa; e traduzir entre unidades, que é onde a atenção humana falha primeiro. Todas essas tarefas têm em comum o fato de que a saída é verificável em segundos por quem a pediu.
A alucinação característica deste assunto. É a confusão entre largura de banda e latência, e ela aparece com uma regularidade que impressiona. Pedi a um assistente uma análise de um serviço em São Paulo consumindo uma API hospedada na Virgínia, com $300$ ms de tempo de resposta observado, e recebi, entre outras coisas, esta recomendação:
Aumentar a largura de banda do enlace de saída de 100 Mbit/s para 1 Gbit/s deve reduzir significativamente o tempo de resposta observado, já que a latência está diretamente relacionada à capacidade disponível do enlace.
A frase é gramaticalmente impecável, tecnicamente confiante e fisicamente falsa. Pela Tabela 2, o piso do RTT nesse par de cidades é $76{,}6$ ms; a resposta de $300$ ms comporta cerca de três idas e voltas mais processamento. Aumentar a taxa do enlace reduz $T_{\text{trans}}$, que para uma requisição de API de alguns kilobytes já era da ordem de dezenas de microssegundos. A recomendação custa dinheiro mensal recorrente e entrega, na melhor das hipóteses, uma melhora de $0{,}1\%$. A correção é a decomposição da Seção 3: identificar quantas idas e voltas a arquitetura exige antes do primeiro byte, e removê-las, que é o que os Artigos 2, 3 e 10 vão ensinar a fazer.
Note por que essa alucinação é difícil de pegar: ela não erra um fato verificável em um documento. Ela erra um modelo físico, e modelos físicos errados produzem texto perfeitamente plausível.
O verificador, em três camadas. Esta é a estrutura que a série usa do primeiro ao último artigo, sempre nesta ordem.
A primeira camada é a sintaxe: o artefato é bem formado? Aqui, isso significa perguntar se as unidades fecham. Uma recomendação que compara $\text{Mbit/s}$ com $\text{ms}$ sem uma terceira grandeza no meio está dimensionalmente errada antes de estar factualmente errada. A análise dimensional é o linter deste assunto, é barata e pega a maior parte dos disparates.
A segunda camada é a semântica: o número proposto respeita a física e as hipóteses declaradas? Para um RTT por uma rota de comprimento $d$ e velocidade de propagação $v$, a propagação sozinha custa pelo menos $2d/v$; usar a distância geodésica e a velocidade na fibra produz um piso geográfico idealizado, não uma descrição da rota real. Da mesma forma, uma janela efetiva $W$ e uma taxa de enlace $R$ impõem o limite $R_{\text{efetiva}}\le\min(R,W/\text{RTT})$. Uma afirmação que viole esses limites sob as mesmas premissas é falsa, independentemente de quão bem escrita esteja. Esta camada é valiosa porque troca confiança por uma conta verificável.
A terceira camada é o raio de explosão, tradução que a série usa para blast radius: se a recomendação estiver errada, o que para de funcionar e quem percebe? Uma recomendação de aumentar banda tem raio de explosão financeiro e reversível. Uma recomendação de reduzir o buffer de um enlace tem raio de explosão operacional e imediato. Uma recomendação de aumentar o tempo limite de uma chamada tem raio de explosão sutil, porque ela funciona até o dia em que a fila cresce e o sistema inteiro para em vez de degradar. A terceira camada é a que os alunos esquecem, e é a que decide se o erro custa um comando de reversão ou um domingo.
Exercício de auditoria. Um assistente produziu o relatório abaixo sobre um serviço com média observada de $51{,}6$ ms, $p_{50}$ de $40$ ms e $p_{99}$ de $1200$ ms, consumido de São Paulo, com servidores em Frankfurt. Encontre os quatro defeitos antes de ler a resposta.
O tempo médio de resposta é de 51,6 ms, dentro do objetivo de 100 ms. O aumento observado no percentil 99 é compatível com sobrecarga de CPU nos servidores de aplicação. Recomenda-se aumentar a largura de banda do enlace e habilitar compressão, o que deve trazer o percentil 99 para próximo da média.
O primeiro defeito é declarar conformidade sem dizer a qual estatística o objetivo de $100$ ms se aplica. Se o objetivo for média, $51{,}6$ ms satisfaz o contrato; se for $p_{95}$ ou $p_{99}$, a conclusão pode ser outra. Além disso, $p_{50}$ e $p_{99}$ não permitem reconstruir a média, razão pela qual o enunciado a fornece como medição independente. A correção não é abolir a média, mas definir o indicador, a janela temporal, a população e o método de cálculo do objetivo.
O segundo defeito só aparece com a Tabela 2 na mão. O piso do RTT entre São Paulo e Frankfurt é de $98{,}3$ ms, e o relatório afirma um $p_{50}$ de $40$ ms para um consumo de São Paulo. Os dois números não podem descrever a mesma coisa. Ou a medição foi tomada no lado do servidor, e então mede processamento e não experiência do usuário, ou há um cache de borda no caminho e o serviço em Frankfurt não é quem responde à mediana das requisições. O relatório não diz onde mediu, e essa omissão invalida todas as conclusões seguintes. É o defeito mais valioso do exercício, porque uma divisão o derruba.
O terceiro defeito é a atribuição a “sobrecarga de CPU” sem nenhuma evidência que a distinga de fila de rede, de reconexão ou de resolução de nome fria. É uma hipótese apresentada como conclusão, e não vem acompanhada do teste que a falsificaria. O Artigo 8 transforma isso em método.
O quarto defeito é a recomendação de banda, já discutida, agravada pela promessa de que o $p_{99}$ ficaria “próximo da média”, que é uma afirmação sobre a forma de uma distribuição feita sem olhar a distribuição. Compressão, aliás, pode até ajudar, mas por outro motivo: ela reduz $L$ e, portanto, $T_{\text{trans}}$, o que só importa se o objeto for grande, coisa que o relatório não verificou.
Quatro defeitos, três camadas. O primeiro falha no contrato estatístico; o segundo, na compatibilidade entre o ponto de medição e o piso geográfico idealizado; o terceiro, na distinção entre hipótese e evidência; e o quarto, no mecanismo causal que ligaria banda ou compressão à cauda. Só depois dessas verificações entra o raio de explosão: ampliar um enlace custa dinheiro e é reversível, enquanto alterar filas, compressão ou limites pode afetar capacidade, CPU e estabilidade. Separar as camadas impede que uma recomendação avance para produção antes de a alegação básica ter sido demonstrada.
10. Conclusão
Este artigo não construiu nenhum protocolo. Ele construiu a régua com que os quinze artigos seguintes serão medidos.
A leitora agora sabe que o encapsulamento cobra um envelope de tamanho fixo e, por isso, que a eficiência precisa ser calculada em relação à mensagem e à fronteira de medição. Em seguida, aprendeu a decompor a latência em propagação, transmissão, processamento e fila, parcelas que respondem a intervenções diferentes. Essa separação mostra por que ampliar a banda ajuda quando a transmissão ou a disputa pelo enlace domina, mas pouco altera um atraso composto por distância, idas e voltas ou processamento remoto.
Além disso, a leitora sabe calcular um piso geográfico idealizado para o RTT e compará-lo com o ponto em que a medição foi tomada. Sabe relacionar janela, RTT e quantidade de dados em voo pelo produto banda-atraso. Na estatística, sabe combinar média, mediana e percentis em vez de pedir que uma única medida descreva toda a distribuição; ao compor chamadas paralelas, sabe também que a probabilidade resultante depende da distribuição conjunta, não apenas dos percentis marginais. Finalmente, o modelo M/M/1 mostrou por que a espera acelera perto da saturação, ao mesmo tempo que deixou explícito que nenhum limiar de utilização, inclusive $80\%$, é universal.
Sabe, por fim, que um modelo de linguagem confunde largura de banda com latência com a mesma serenidade com que acerta o resto, e que a defesa contra isso não é desconfiança genérica: é uma divisão, feita em dez segundos, comparando o número proposto com $2d/v$.
A física fixa o piso. O que está acima do piso é decisão de protocolo, e a primeira decisão que qualquer protocolo de transporte precisa tomar é o que fazer quando um pacote se perde: pedir de novo e esperar, ou seguir em frente e aceitar o buraco. O próximo artigo abre o transporte, e mostra que essa escolha aparentemente simples determina a arquitetura inteira de um sistema distribuído.
Acrônimos e Abreviações neste artigo
| Acrônimo | Definição em Inglês | Tradução em Português |
|---|---|---|
BDP |
Bandwidth-Delay Product | Produto Banda-Atraso |
BGP |
Border Gateway Protocol | Protocolo de Roteamento de Borda |
CPU |
Central Processing Unit | Unidade Central de Processamento |
DNS |
Domain Name System | Sistema de Nomes de Domínio |
ICMP |
Internet Control Message Protocol | Protocolo de Mensagens de Controle da Internet |
IP |
Internet Protocol | Protocolo de Internet |
ISO |
International Organization for Standardization | Organização Internacional de Normalização |
MSS |
Maximum Segment Size | Tamanho Máximo de Segmento |
MTU |
Maximum Transmission Unit | Unidade Máxima de Transmissão |
OSI |
Open Systems Interconnection | Interconexão de Sistemas Abertos |
QUIC |
QUIC (nome próprio, originalmente Quick UDP Internet Connections) | QUIC |
RFC |
Request for Comments | Pedido de Comentários |
RTP |
Real-time Transport Protocol | Protocolo de Transporte em Tempo Real |
RTT |
Round-Trip Time | Tempo de Ida e Volta |
TCP |
Transmission Control Protocol | Protocolo de Controle de Transmissão |
TLS |
Transport Layer Security | Segurança da Camada de Transporte |
UDP |
User Datagram Protocol | Protocolo de Datagrama de Usuário |
Referências
BONAVENTURE, O. Computer Networking: Principles, Protocols and Practice. 3. ed. Université catholique de Louvain. Disponível em: https://www.computer-networking.info/. Acesso em: 8 ago. 2026.
BONICA, R.; BAKER, F.; HUSTON, G.; HINDEN, R.; TROAN, O.; GONT, F. RFC 8900: IP Fragmentation Considered Fragile. IETF, 2020. Disponível em: https://www.rfc-editor.org/rfc/rfc8900. Acesso em: 8 ago. 2026.
BORMAN, D.; BRADEN, B.; JACOBSON, V.; SCHEFFENEGGER, R. (ed.). RFC 7323: TCP Extensions for High Performance. IETF, 2014. Disponível em: https://www.rfc-editor.org/rfc/rfc7323. Acesso em: 8 ago. 2026.
BOZKURT, I. N.; AQEEL, W.; BHATTACHERJEE, D.; CHANDRASEKARAN, B.; GODFREY, P. B.; LAUGHLIN, G.; MAGGS, B. M.; SINGLA, A. Dissecting Latency in the Internet’s Fiber Infrastructure. 2018. Disponível em: https://arxiv.org/abs/1811.10737. Acesso em: 8 ago. 2026.
BRADEN, R. (ed.). RFC 1122: Requirements for Internet Hosts: Communication Layers. IETF, 1989. Disponível em: https://www.rfc-editor.org/rfc/rfc1122. Acesso em: 8 ago. 2026.
DEERING, S.; HINDEN, R. RFC 8200: Internet Protocol, Version 6 (IPv6) Specification. IETF, 2017. Disponível em: https://www.rfc-editor.org/rfc/rfc8200. Acesso em: 8 ago. 2026.
EDDY, W. (ed.). RFC 9293: Transmission Control Protocol (TCP). IETF, 2022. Disponível em: https://www.rfc-editor.org/rfc/rfc9293. Acesso em: 8 ago. 2026.
GETTYS, J.; NICHOLS, K. Bufferbloat: Dark Buffers in the Internet. Communications of the ACM, v. 55, n. 1, p. 57–65, 2012. Disponível em: https://queue.acm.org/detail.cfm?id=2071893. Acesso em: 8 ago. 2026.
GRIGORIK, I. High Performance Browser Networking. Sebastopol: O’Reilly, 2013. Disponível em: https://hpbn.co/. Acesso em: 8 ago. 2026.
INTERNATIONAL ORGANIZATION FOR STANDARDIZATION. ISO/IEC 7498-1: Information technology: Open Systems Interconnection: Basic Reference Model: The Basic Model. Genebra: ISO, 1994. Disponível em: https://www.iso.org/standard/20269.html. Acesso em: 8 ago. 2026.
KINGMAN, J. F. C. The Single Server Queue in Heavy Traffic. Mathematical Proceedings of the Cambridge Philosophical Society, v. 57, n. 4, p. 902–904, 1961. DOI: 10.1017/S0305004100036094. Disponível em: https://www.cambridge.org/core/journals/mathematical-proceedings-of-the-cambridge-philosophical-society/article/abs/single-server-queue-in-heavy-traffic/81C55BC00A68FE6D5385638AA0B0AF37. Acesso em: 8 ago. 2026.
KLEINROCK, L. Queueing Systems, Volume 1: Theory. New York: Wiley-Interscience, 1975.
LITTLE, J. D. C. A Proof for the Queuing Formula $L = \lambda W$. Operations Research, v. 9, n. 3, p. 383–387, 1961. DOI: 10.1287/opre.9.3.383. Disponível em: https://pubsonline.informs.org/doi/10.1287/opre.9.3.383. Acesso em: 8 ago. 2026.
MASSACHUSETTS INSTITUTE OF TECHNOLOGY. 6.02 Introduction to EECS II: Digital Communication Systems. MIT OpenCourseWare. Disponível em: https://ocw.mit.edu/courses/6-02-introduction-to-eecs-ii-digital-communication-systems-fall-2012/. Acesso em: 8 ago. 2026.
MICROSOFT. C++ Standard Library Header Files. Microsoft Learn. Disponível em: https://learn.microsoft.com/en-us/cpp/standard-library/cpp-standard-library-header-files?view=msvc-170. Acesso em: 8 ago. 2026.
MICROSOFT. /std (Specify Language Standard Version). Microsoft Learn. Disponível em: https://learn.microsoft.com/en-us/cpp/build/reference/std-specify-language-standard-version?view=msvc-170. Acesso em: 8 ago. 2026.
NICHOLS, K.; JACOBSON, V. Controlling Queue Delay. ACM Queue, v. 10, n. 5, 2012. Disponível em: https://queue.acm.org/detail.cfm?id=2209336. Acesso em: 8 ago. 2026.
PETERSON, L.; DAVIE, B. Computer Networks: A Systems Approach. Edição aberta. Disponível em: https://book.systemsapproach.org/. Acesso em: 8 ago. 2026.
POSTEL, J. RFC 791: Internet Protocol. IETF, 1981. Disponível em: https://www.rfc-editor.org/rfc/rfc791. Acesso em: 8 ago. 2026.
RIPE NCC. RIPE Atlas. Disponível em: https://atlas.ripe.net/. Acesso em: 8 ago. 2026.
SALTZER, J. H.; REED, D. P.; CLARK, D. D. End-to-End Arguments in System Design. ACM Transactions on Computer Systems, v. 2, n. 4, p. 277–288, 1984. DOI: 10.1145/357401.357402.
SCHULZRINNE, H.; CASNER, S.; FREDERICK, R.; JACOBSON, V. RFC 3550: RTP: A Transport Protocol for Real-Time Applications. IETF, 2003. Disponível em: https://www.rfc-editor.org/rfc/rfc3550. Acesso em: 8 ago. 2026.
STANFORD UNIVERSITY. CS 144: Introduction to Computer Networking. Disponível em: https://cs144.github.io/. Acesso em: 8 ago. 2026.
UNIVERSITY OF CALIFORNIA, BERKELEY. CS 168: Introduction to the Internet: Architecture and Protocols. Disponível em: https://cs168.io/. Acesso em: 8 ago. 2026.
Índice da Série: Redes para Engenharia de Software
- 1. A Pilha TCP/IP e a Física da Rede (Você está aqui)
- 2. Transporte: TCP, UDP e QUIC
(Updated: )