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. Da Rede Local à Web: Dispositivos, Topologias e Serviços
- 3. Camada IP: Endereçamento, Sub-redes e Encaminhamento
- 4. 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.
Por falar em vocabulário, antes das camadas vamos definir uma base de conhecimento mínima: uma rede de computadores é um conjunto de dispositivos capazes de trocar dados por caminhos de comunicação. O computador, o telefone e o servidor são dispositivos finais; cada ponto pelo qual um deles se conecta à rede é uma interface. Uma conexão direta entre duas interfaces forma um enlace, que pode usar um cabo de cobre, fibra óptica ou ondas de rádio. Dentro de uma rede local, um comutador, também chamado de switch, encaminha dados entre interfaces próximas. Para alcançar outra rede, os dados passam por um roteador, equipamento que escolhe o próximo enlace do caminho. A Internet não é um único fio nem um único equipamento: é uma rede de redes interligadas por roteadores.
A Figura 1 reúne esses objetos em um único caminho. Os dispositivos finais pertencem às redes locais das pontas; entre elas, cada roteador recebe os dados por uma interface e escolhe o próximo enlace, salto após salto.
Figura 1: A Internet não é um único enlace. Dispositivos finais comunicam-se por interfaces e enlaces dentro das redes locais, enquanto roteadores conectam essas redes, salto após salto.
1. Duas pilhas e uma decisão de engenharia
Depois que definimos as bases, 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 no mercado. A pilha que estava rodando venceu. Quem diria? O modelo perdedor sobreviveu como vocabulário e registro histórico. É 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, porém 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 uma implementação separada na Internet: o que elas descrevem virou uma responsabilidade da aplicação, ou de bibliotecas dentro dela. Quando alguém diz que TLS é camada 6, está fazendo uma analogia útil mas 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 uma 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. Algumas pessoas precisam de representações gráficas para entender. Pensando nisso, a Figura 2 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 2: 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.
Por essas camadas circulam as informações. Mas antes de continuarmos a atenta leitora precisa saber que Mensagem, segmento, datagrama, pacote e quadro não são exatamente sinônimos.
A aplicação produz uma mensagem, isto é, os bytes cujo significado interessa ao programa. O protocolo TCP organizará parte desses bytes em um segmento; o UDP os transportará em um datagrama UDP. O datagrama é a estrutura completa que viaja pela rede, contendo as informações de controle (para chegar ao destino) e os dados úteis. A camada de Internet colocará essa unidade dentro de um pacote IP, também chamado de datagrama IP. Por fim, a camada de enlace coloca o pacote dentro de um quadro para atravessar um enlace específico. No meio físico, o quadro torna-se uma sequência de bits representada por sinais elétricos, luminosos ou de rádio. No uso cotidiano, pacote também funciona como termo genérico para uma unidade de dados da rede; quando o tamanho ou o cabeçalho importar, vamos nomear a camada para eliminar a ambiguidade.
A Figura 3 acompanha uma mensagem enquanto ela desce pela pilha. O azul preserva a unidade recebida da camada anterior; o violeta marca as informações de controle acrescentadas para formar a nova unidade.
Figura 3: Cada camada conserva como carga útil a unidade recebida e acrescenta seu próprio controle. Por isso, os mesmos dados recebem nomes diferentes conforme a fronteira observada.
Essa compressão, e as camadas, esclarecem o vocabulário, mas ainda não explica por que as fronteiras foram colocadas nesses pontos. A questão precisa ser resolvida por quem escreve software, 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, desde então, continua sendo a coisa mais útil já escrita sobre arquitetura de sistemas distribuídos: o argumento fim a fim.
O argumento de Saltzer, Reed e Clark diz que 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 valida o arquivo lido no destino contra o arquivo que o remetente pretendia enviar.
A consequência prática é uma rede burra no meio e inteligente nas pontas.
O protocolo 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 à evolução entre enlaces de nove mil bits por segundo e enlaces de quatrocentos gigabits por segundo, e da evolução de aplicações de terminal remoto para aplicações de videoconferência. Uma camada competente 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 desta série. Quando o Artigo 14 mostrar um service mesh interceptando cada requisição para acrescentar repetição, tempo limite e telemetria, valerá seu tempo e esforço, parar para perguntar se a função foi colocada no lugar certo, ou se estamos implementando no meio do percurso o que só a ponta pode garantir.
Há 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 transmissão, 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
A primeira coisa que a atenta leitora precisa entender é que cada camada embrulha o que recebe da camada de cima. A aplicação entrega um payload (carga útil), o transporte acrescenta um cabeçalho, a camada de Internet acrescenta outro cabeçalho, o enlace acrescenta o seu próprio cabeçalho e ainda um encerramento. O resultado atravessa o fio, ou link de conexão, como uma boneca russa, para ser desmontado na ordem inversa no destino.
O que é Ethernet? Ethernet é uma família de tecnologias de enlace usada principalmente em redes locais cabeadas. Ela define como organizar um quadro, como identificar interfaces no enlace por endereços MAC, de Media Access Control (controle de acesso ao meio), e como representar os bits em diferentes meios físicos. Ethernet não é sinônimo de Internet: um quadro Ethernet vale apenas no enlace em que está sendo transportado e pode ser substituído por um quadro Wi-Fi no salto seguinte, enquanto o pacote IP permanece como a unidade encaminhada entre redes. Também não é sinônimo de cabo. O mesmo formato lógico de enlace possui variantes físicas para cobre e fibra, com taxas e alcances diferentes.
Precisamos de um número antes de prosseguir, uma métrica.
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. Parece bom.
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. As vezes a mesma pergunta admite duas respostas diferentes conforme a fronteira escolhida. A eficiência de quadro será definida como a fração dos bytes que atravessam o fio carregando dado útil da aplicação. A parte carregando dados úteis é importante. Sendo assim, teremos:
\[\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 será dado pela soma fixa:
\[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 de dados; por isso, entram nos cálculos de pacotes por segundo e de goodput, como o do exercício 4.
O goodput é a taxa de transferência da informação que realmente importa para a aplicação que está recebendo os dados. É a quantidade de payload (carga útil) entregue com sucesso e sem erros ao destino, por unidade de tempo.
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 será dada por
\[\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 16 vai comparar REST, gRPC e WebSocket exatamente com essa régua, e o Artigo 17 vai mostrar protocolos desenhados por gente que contava bytes.
A Figura 4 mostra os dois regimes lado a lado, com a mesma MTU e payloads de tamanhos diferentes.
Figura 4: 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 é uma propriedade do protocolo, e sim da razão entre a mensagem e o 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 11 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 será dada por
\[\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 7 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
A 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 será dado pela soma da propagação e da transmissão em cada enlace, além da fila e do 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 será dado pelo 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 será dado pelo tempo necessário 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 5 mostra os dois regimes empilhados, com as mesmas parcelas e proporções invertidas.
Figura 5: 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 12 vai quantificar.
O modelo M/M/1 é o sistema de filas mais clássico da teoria das filas (notação de Kendall). Ele descreve um único servidor com as seguintes hipóteses:
- Primeiro M: processo de chegadas Markoviano — os intervalos entre chegadas são exponenciais, ou seja, as chegadas formam um processo de Poisson de taxa $\lambda$.
- Segundo M: tempos de serviço Markovianos — cada atendimento (transmissão de um pacote, no contexto de redes) também é exponencial, com taxa $\mu$.
- 1: um único servidor (um enlace, uma interface de roteador, etc.).
A fila é em geral considerada infinita e a disciplina é obedecer a regra: primeiro a chegar, primeiro a ser servido. O sistema só é estável se $\lambda < \mu$. A utilização é $\rho = \lambda/\mu$.
O tempo de transmissão de um pacote ($L/R$) e o atraso de propagação dependem só do tamanho do pacote, da taxa do enlace e da distância. O tempo de fila, porém, depende de quando os pacotes chegam e de quão variável é o tempo de serviço. Sem declarar o processo de chegada e a distribuição do serviço, a folha de dados do enlace não basta. O M/M/1 é o primeiro modelo que fecha essas hipóteses e entrega fórmulas fechadas.
Resultados principais
- Número médio de pacotes no sistema: $N = \dfrac{\rho}{1-\rho}$
- Tempo médio no sistema (fila + transmissão): $T = \dfrac{1}{\mu-\lambda}$
- Tempo médio só na fila: $W = \dfrac{\rho}{\mu(1-\rho)} = \dfrac{\lambda}{\mu(\mu-\lambda)}$
- Número médio na fila: $L_q = \dfrac{\rho^2}{1-\rho}$
Essa é a matemática. Essas expressões vêm da cadeia de Markov de nascimento-e-morte associada ao sistema e da lei de Little.
Em redes de computadores o M/M/1 é usado como primeira aproximação para a fila de um enlace: $\lambda$ é a taxa média de chegada de pacotes e $\mu = R/\overline{L}$ (taxa do enlace dividida pelo tamanho médio do pacote). Depois costuma-se relaxar as hipóteses (M/G/1, M/D/1, limites de tráfego intenso etc.), exatamente como o texto indica que a Seção 7 fará.
A lei de Little, por sua vez, relaciona o número médio de clientes (ou pacotes) no sistema com o tempo médio que cada um permanece nele. Na forma mais usada:
\[L = \lambda W\]
- $L$: número médio de pacotes no sistema (fila + serviço);
- $\lambda$: taxa média de chegada (pacotes por unidade de tempo);
- $W$: tempo médio que um pacote passa no sistema.
A mesma relação vale só para a fila:
\[L_q = \lambda W_q\]na qual $L_q$ é o número médio na fila e $W_q$ o tempo médio de espera na fila.
A lei não depende da distribuição das chegadas, da distribuição dos tempos de serviço, do número de servidores nem da disciplina da fila. Basta o sistema ser estável (não crescer indefinidamente) e as médias existirem. Por isso vale para M/M/1, M/G/1, G/G/1 e muitos outros modelos.
No M/M/1 ela liga as duas faces do resultado: uma vez obtido o número médio $N = \rho/(1-\rho)$ pela cadeia de Markov, o tempo médio sai imediatamente:
\[T = \frac{N}{\lambda} = \frac{1}{\mu-\lambda}.\]O tempo só de fila segue o mesmo caminho: $W = L_q/\lambda$.
Em regime permanente, o fluxo que entra é igual ao que sai. Se, em média, há $L$ pacotes no sistema e cada um permanece $W$ unidades de tempo, então a taxa de “rotatividade” é $L/W$, que deve coincidir com $\lambda$.
Em redes isso permite passar de uma grandeza fácil de medir (ocupação média de um buffer) para o atraso médio percebido, sem precisar da distribuição completa dos tempos.
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.
Semiverseno?
A palavra semiverseno refere-se à fórmula do semiverseno (conhecida em inglês como Haversine formula).Trata-se de uma equação matemática da trigonometria esférica utilizada para calcular a distância mais curta entre dois pontos sobre a superfície de uma esfera, a partir das suas coordenadas de latitude e longitude.O conceito matemático.
O nome “semiverseno” significa literalmente a “metade do seno verso” (uma função trigonométrica clássica). A função do semiverseno para um ângulo $\theta$ é expressa da seguinte forma: \(\text{hav}(\theta) = \sin^2\left(\frac{\theta}{2}\right) = \frac{1 - \cos(\theta)}{2}\) Neste caso, a fórmula do semiverseno está sendo aplicada para descobrir a distância geográfica real entre a cidade de São Paulo e as cidades que abrigam as cinco regiões de nuvem (data centers) que usamos como exemplo na Tabela.
Como o planeta Terra tem um formato aproximadamente esférico, calcular a distância em linha reta em um mapa bidimensional (geometria plana ou euclidiana) geraria distorções significativas.
A fórmula do semiverseno corrige isso, medindo a distância curva acompanhando o relevo da superfície terrestre. Em computação em nuvem e redes, essa distância física calculada pela fórmula é frequentemente utilizada para estimar o piso ou o limite físico mínimo de latência (o tempo que um pacote de dados leva para viajar pela fibra óptica de uma cidade a outra).
A palavra piso faz um trabalho pesado na Tabela 2. 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$. A atenta leitora deve ter em mente que esses valores descrevem especificamente o conjunto de rotas estudado por Bozkurt, não uma constante mundial, e servem apenas para mostrar por que multiplicar a geodésica por um fator escolhido de memória não substituirá o ato de 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. Seguem um caminho real que pode ser muito, muito maior.
A segunda fonte de excesso é 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 fonte de excesso é a fila, que é variável, depende da hora do dia e é o assunto da Seção 7.
O que é uma fila em redes de computadores?
Spoiler Alert! não é a fila do pão, mas tem relação.
Como vimos antes, em uma rede, as informações (como um vídeo ou uma mensagem de texto) não viajam inteiras. Elas são divididas em pequenos pedaços chamados de “pacotes”. Esses pacotes viajam pelas conexões da internet passando por equipamentos chamados roteadores, que funcionam como cruzamentos de trânsito direcionando o fluxo de dados.
Uma fila é uma linha de espera temporária para esses pacotes dentro da memória de um roteador. É o equivalente digital a uma fila de carros aguardando a sua vez em uma praça de pedágio.
As filas se formam devido a diferenças na velocidade ou no volume de dados. Isso acontece em duas situações principais:
- Volume de chegada superior à capacidade de saída: Muitos computadores tentam enviar dados ao mesmo tempo para o mesmo equipamento. O roteador recebe os pacotes mais rápido do que consegue processá-los e enviá-los adiante.
- Afunilamento na rede (Gargalo): Os dados chegam por uma conexão rápida e de alta capacidade, mas precisam sair por uma conexão mais lenta ou restrita.
Para não descartar esses dados imediatamente, o equipamento os guarda temporariamente em sua memória (chamada de buffer), organizando a fila. Cada pacote aguarda a sua vez de seguir viagem. O tempo que os pacotes passam ali parados gera um atraso na comunicação e, se a memória do roteador encher completamente, os próximos pacotes que chegarem serão descartados, exigindo que o dispositivo de origem envie tudo novamente.
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 os valores extremos. 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 12.
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 6 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 será dado por
\[\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 4 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 será dada por
\[\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 14 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 chamaremos 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.
Na 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 criar um modelo didático.
Suponha que cabeçalhos ocupem $3\%$ da vazão e que, dos bytes restantes destinados a dados, $2\%$ repitam bytes já enviados. Neste caso, 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 é importante 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. Porém, sem sentido ou uso prático.
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}\]Observe que 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. Muito pouco.
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 4 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 será dada por
\[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 será dado pelo 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, peso e consequência.
O jitter é a variação do atraso, e não o atraso. Para medi-lo, precisamos comparar o espaçamento de dois pacotes na origem com o espaçamento do mesmo par no destino. Vamos chamar de $S_i$ o instante de envio do pacote $i$ e de $R_i$ seu instante de chegada. A RFC 3550, que padroniza o RTP (Real-time Transport Protocol), define a diferença entre esses espaçamentos como
\[D_i = (R_i - R_{i-1}) - (S_i - S_{i-1})\]e o estimador incremental de jitter será definido como
\[J_i = J_{i-1} + \frac{\vert D_i \vert - J_{i-1}}{16}\]Se $D_i$ for positivo, o par chegou mais espaçado do que saiu. Se for negativo, chegou mais comprimido. O estimador usa $\vert D_i\vert$ porque os dois movimentos representam variação, embora tenham sinais opostos.
Vamos iniciar o estimador com $J_0 = 0$. O ganho $1/16$ especificado pela RFC 3550 limita a influência de uma única observação, mas também retarda a convergência. Se $\vert D_i\vert$ permanecer constante, a fração da mudança incorporada depois de $n$ atualizações será
\[1-\left(\frac{15}{16}\right)^n.\]Com $n=16$, essa fração vale $64{,}4\%$; com $n=48$, $95{,}5\%$; e com $n=72$, $99{,}0\%$. Portanto, os primeiros pacotes de um fluxo iniciado com $J_0=0$ produzem uma estimativa transitória, ainda abaixo do regime que seria observado se a variação permanecesse estável.
Para interpretar $D_i$, acompanhe apenas os espaçamentos. Se dois pacotes saem separados por $10$ ms e chegam separados por $15$ ms, então $D_i=15-10=5$ ms. A comparação não informa o atraso absoluto de nenhum dos dois pacotes; informa apenas que o intervalo entre eles aumentou $5$ ms.
Vamos agora aplicar essa definição a um fluxo curto.
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. O desvio padrão amostral desses valores é $8{,}11$ ms, enquanto a amplitude é $32-11=21$ ms. Depois de sete atualizações, o estimador da RFC 3550 devolve $J=4{,}25$ ms.
Esse resultado não deveria coincidir com o desvio padrão. As duas métricas têm definições, memórias e finalidades diferentes. Além disso, o ganho $1/16$ mantém $J$ no regime transitório durante o início do fluxo. Quem lê o estimador nos primeiros segundos precisa registrar também quantas atualizações já ocorreram.
Agora vamos passar do fluxo de pacotes para uma decisão de produto. Considere dez medições de atraso de ida, em milissegundos:
\[18,\ 21,\ 19,\ 24,\ 20,\ 22,\ 19,\ 140,\ 21,\ 20.\]Quando representamos uma distribuição de valores em uma linha ou em um histograma, a região que concentra a maioria das observações forma o corpo da distribuição. As regiões menos densas que se prolongam em direção aos valores extremos recebem o nome de caudas. Nesta amostra, nove atrasos se concentram entre $18$ e $24$ ms, enquanto a observação de $140$ ms estende a distribuição para o lado dos valores altos. Esse lado será a cauda direita, ou cauda superior. Como atrasos elevados são o risco relevante em redes, daqui em diante usaremos cauda, sem qualificação, para nos referirmos a essa região superior.
A Figura 6 coloca as dez observações na mesma escala linear. A faixa azul delimita o corpo observado entre $18$ e $24$ ms, não uma fronteira universal para toda distribuição. A seta âmbar indica a direção da cauda direita, e o ponto de $140$ ms mostra quanto uma observação legítima e rara pode se afastar da concentração principal.
Figura 6: Nove atrasos ocupam os seis milissegundos entre $18$ e $24$ ms, enquanto $140$ ms aparece $116$ ms depois da maior observação do corpo. Esse afastamento estende a cauda direita sem, por si só, autorizar o descarte da medição.
Uma cauda não é sinônimo de erro de medição nem de valor atípico. Ela pode reunir observações legítimas, embora raras, produzidas por filas, retransmissões, pausas do sistema ou caminhos diferentes na rede. Um valor só poderá ser descartado depois que identificarmos uma falha de coleta ou demonstrarmos que ele não pertence à população estudada. Sem essa evidência, removê-lo porque parece grande apagaria justamente a experiência lenta que pretendemos medir.
Para calcular a média, somamos todas as observações e dividimos por dez:
\[\bar{x}=\frac{18+21+19+24+20+22+19+140+21+20}{10} =\frac{324}{10}=32{,}4\ \text{ms}.\]Para calcular a mediana, ordenamos a amostra. Os dois valores centrais são $20$ e $21$ ms, logo
\[p_{50}=\frac{20+21}{2}=20{,}5\ \text{ms}.\]A média é maior que nove das dez observações porque o valor de $140$ ms participa da soma com toda a sua magnitude. Se o removermos, a média cai $36{,}9\%$, para $20{,}44$ ms, enquanto a mediana cai $2{,}4\%$, para $20$ ms. A mediana também pode mudar quando removemos ou acrescentamos observações, mas é menos sensível à magnitude de um extremo.
A média, sozinha, é insuficiente para descrever latência. Ela será ú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, vamos chamar de $p_q$ o percentil de ordem $q$, isto é, o valor abaixo do qual se encontra a fração $q$ das observações. Assim, o percentil $p_{50}$ é a mediana: $50\%$ das observações ficam abaixo dele. O $p_{95}$ deixa $95\%$ abaixo e os $5\%$ mais altos acima; o percentil $p_{99}$ deixa $99\%$ abaixo e apenas o $1\%$ mais alto acima. Quanto maior o índice, mais profundamente o percentil descreve a cauda de latências elevadas. Em uma amostra finita, contudo, o percentil pode cair entre duas observações, e por isso o método usado para escolher ou interpolar esses valores precisa ser declarado.
Vamos tornar esse problema visível com os dez atrasos da amostra acima. Depois de ordená-los, obtemos $18, 19, 19, 20, 20, 21, 21, 22, 24, 140$ ms. O método linear implementado na Seção 8 calcula primeiro a posição, com índice iniciado em zero, por $k=(n-1)q$. Para $n=10$ observações e $q=0{,}95$, teremos
\[k=(10-1)\times 0{,}95=8{,}55.\]A posição $8{,}55$ fica a $55\%$ do caminho entre o elemento de índice $8$, o nono valor, que vale $24$ ms, e o elemento de índice $9$, o décimo valor, que vale $140$ ms. A interpolação será, portanto,
\[p_{95}=24+0{,}55(140-24)=24+63{,}8=87{,}8\ \text{ms}.\]Se escolhermos o vizinho mais próximo em vez de interpolar, arredondamos a posição $8{,}55$ para o índice $9$ e obtemos $p_{95}=140$ ms. Os dois resultados obedecem aos respectivos contratos; a enorme diferença entre eles denuncia que dez observações não sustentam uma conclusão estável sobre a cauda.
A Figura 7 concentra-se agora na decisão que falta. Os dez valores aparecem igualmente espaçados por índice, e a posição $8{,}55$ atravessa $55\%$ do intervalo entre os dois maiores. A figura separa o método que interpola essa distância do método que escolhe uma observação da amostra.
Figura 7: A mesma posição $8{,}55$ produz $87{,}8$ ms por interpolação linear e $140$ ms pelo vizinho mais próximo. O método de quantil faz parte da definição do resultado, e por isso precisa acompanhar o percentil relatado.
Podemos entender também de onde vem a recomendação de coletar muito mais dados. Acima de $p_q$ resta a fração $1-q$ da distribuição; em $n$ observações, esperamos encontrar aproximadamente $n(1-q)$ valores nessa região. Se adotarmos como regra mínima esperar dez valores além do percentil, teremos $n(1-q)\approx 10$. Para $p_{99}$, a fração superior é $1-0{,}99=0{,}01$, logo $n\approx 10/0{,}01=1000$ amostras. Para $p_{99{,}9}$, ela é $1-0{,}999=0{,}001$, logo $n\approx 10/0{,}001=10\,000$ amostras. Trata-se de uma contagem esperada, não de uma garantia de que aparecerão exatamente dez valores nem de que o percentil será preciso; a regra apenas evita tentar descrever 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 12, quando um balanceador distribuir requisições, e no Artigo 14, 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. A única variável disponível será 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 o controle até $50$ ms. As métricas e o histograma responderão durante o movimento, enquanto o globo acompanhará o trecho seguinte da rota.
O laboratório gera perturbações centradas em pares opostos. Por construção, a média permanece no atraso-base, mas 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,
\[\bar{x}=\frac{324}{10}=32{,}4\ \text{ms}.\]Depois de ordenar a amostra como $18, 19, 19, 20, 20, 21, 21, 22, 24, 140$, encontramos os valores centrais $20$ e $21$. Como $n=10$ é par, a mediana será
\[\widetilde{x}=\frac{20+21}{2}=20{,}5\ \text{ms}.\]Para o desvio padrão amostral, precisamos medir os afastamentos em relação a $\bar{x}=32{,}4$ ms. A soma dos quadrados desses afastamentos é
\[\sum_{i=1}^{10}(x_i-\bar{x})^2=12\,890{,}40\ \text{ms}^2.\]Como estimamos a dispersão a partir de uma amostra, dividimos por $n-1=9$:
\[s=\sqrt{\frac{12\,890{,}40}{9}}=37{,}85\ \text{ms}.\]Sem a observação de $140$ ms, a soma cai para $184$ e restam nove valores. A nova média é $184/9=20{,}44$ ms, e a mediana é o quinto valor ordenado, $20$ ms. Nesse caso, a soma dos quadrados dos afastamentos é $26{,}22\ \text{ms}^2$. Assim,
\[s_{\text{sem }140}=\sqrt{\frac{26{,}22}{9-1}}=1{,}81\ \text{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$ | $\vert D_i\vert$ | $J_i = J_{i-1} + (\vert D_i\vert - 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, obtemos $18, 19, 19, 20, 20, 21, 21, 22, 24, 140$ ms.
Com $B=30$ ms, apenas $140>30$, portanto a fração tardia é $1/10=10\%$. Com $B=100$ ms, ainda temos apenas $140>100$, e a fração permanece $1/10=10\%$. A linha com $B=150$ ms completa a comparação ao mostrar o valor necessário para absorver toda esta amostra.
| $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. Ela quase desaparece sob carga leve e pode dominar a resposta perto da saturação. Por isso, não conseguimos obtê-la apenas da distância, da taxa nominal do enlace ou 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 será dada pela razão
\[\rho = \frac{\lambda}{\mu}\]adimensional. O valor $\rho=0{,}8$, por exemplo, significa que o servidor permanece ocupado durante $80\%$ do tempo. Em um modelo com fila ilimitada, $\rho\ge1$ torna o sistema instável: a taxa média de chegada alcança ou supera a capacidade média de serviço, e o tamanho esperado da fila não converge. Uma fila real tem memória finita e começa a descartar antes de crescer sem limite. Toda a análise a seguir supõe $\rho\lt1$.
O modelo mais simples que preserva esse mecanismo é a fila M/M/1: chegadas segundo um processo de Poisson, tempos de serviço exponenciais, um único servidor e atendimento por ordem de chegada. Este modelo não descreve todo tráfego real. Serve como referência porque declara hipóteses que podemos confrontar com as medições.
O processo de Poisson é o modelo padrão de chegadas aleatórias no tempo. Diz-se que os eventos (chegada de pacotes, por exemplo) formam um processo de Poisson de taxa $\lambda$ quando:
- o número de eventos em qualquer intervalo de duração $t$ segue uma distribuição de Poisson com média $\lambda t$;
- os intervalos entre eventos consecutivos são independentes e exponenciais de parâmetro $\lambda$ (média $1/\lambda$);
- a probabilidade de dois ou mais eventos no mesmo instante infinitesimal é desprezível.
A propriedade mais importante é a falta de memória: o tempo que falta até a próxima chegada não depende de quanto tempo já se passou desde a última. Por isso o processo é chamado Markoviano — daí o primeiro “M” da notação M/M/1.
Por que aparece no modelo de fila
O tempo de fila depende do processo de chegadas, não só da taxa média. Sem uma hipótese sobre quando os pacotes chegam, não há fórmula. O processo de Poisson é a hipótese mais simples e tratável: basta conhecer $\lambda$.
Em redes, ele surge como aproximação quando muitos fluxos independentes se superpõem (teorema do limite de Poisson): o tráfego agregado se comporta como Poisson mesmo que cada fluxo individual não seja.
Resultados úteis
- $P(N(t)=k) = e^{-\lambda t}\dfrac{(\lambda t)^k}{k!}$
- Tempo até a próxima chegada: $P(X>t)=e^{-\lambda t}$
- Superposição: a soma de processos de Poisson independentes ainda é Poisson, com taxa igual à soma das taxas.
- Divisão aleatória (splitting): se cada chegada é encaminhada independentemente com probabilidade $p$, o processo resultante também é Poisson de taxa $p\lambda$.
No M/M/1, $\lambda$ é exatamente a taxa desse processo de Poisson de chegadas de pacotes no enlace. A segunda hipótese (serviço exponencial) completa o modelo e permite as fórmulas de atraso médio.
Continuando nossa análise, vamos primeiro calcular o tempo médio total $W$, que inclui espera e serviço. Para uma fila M/M/1. Para tanto, teremos:
\[W = \frac{1}{\mu - \lambda} = \frac{1}{\mu(1 - \rho)},\]O termo $1/\mu$ é o tempo médio de serviço. Para isolar apenas a espera anterior ao serviço, vamos subtraí-lo de $W$:
\[W_q = W - \frac{1}{\mu} = \frac{\rho}{\mu - \lambda} = \frac{\rho}{\mu(1-\rho)}.\]A lei de Little, que examinaremos em seguida, transforma esses tempos em quantidades médias de pacotes. Para o sistema inteiro e para a fila, respectivamente,
\[L = \lambda W = \frac{\rho}{1 - \rho}, \qquad L_q = \lambda W_q = \frac{\rho^2}{1 - \rho}.\]Agora a distinção está explícita: $W$ inclui o tempo de serviço de $1/\mu$, enquanto $W_q$ mede somente a espera. Em ambas as expressões, o denominador $1-\rho$ encolhe à medida que a utilização cresce.
Vamos fixar $\mu=1000$ pacotes/s. Cada serviço leva, em média, $1/1000$ s, ou $1$ ms. A Tabela 3 mostra o que acontece quando mantemos essa capacidade e aumentamos apenas a chegada.
| $\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 8 mostra a curva, e vale olhá-la por um instante antes de continuar.
Figura 8: 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, que não exige chegadas de Poisson nem tempos de serviço exponenciais. Para um sistema estável, observado durante um intervalo representativo e com médias de longo prazo bem definidas, a lei de Little estabelece que
\[L = \lambda W,\]na qual $L$ é o número médio de itens dentro da fronteira observada, $\lambda$ é a taxa média com que eles entram e $W$ é o tempo médio que cada item permanece ali. A fronteira precisa ser a mesma nas três grandezas. Com esse cuidado, a identidade serve para pacotes em um roteador, requisições em um servidor, pedidos em uma fábrica e pessoas em uma fila.
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 12, para dimensionar instâncias, e no Artigo 26, para planejar capacidade.
Vamos fechar com a patologia que resume a seção. A memória ficou barata, e buffers generosos pareceram uma forma simples de evitar descartes. O custo oculto dessa escolha recebe o nome de bufferbloat: o enlace continua entregando dados, mas uma fila excessiva transforma congestionamento em latência. Considere um enlace de $10$ Mbit/s com um buffer de $256$ MB completamente ocupado. O tempo necessário para drená-lo será
\[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 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 tardio.
Uma confirmação percorre o sentido inverso e só sofre a mesma fila se também houver gargalo naquele sentido. Portanto, não devemos imaginar um único pacote de controle universalmente preso atrás dos dados. Ainda assim, para o 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 determinam o que a leitora verá. A parcela de fila reúne dois efeitos distintos: 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. Assim, o laboratório mantém visível o que vem da taxa do enlace e o que vem da competição com terceiros.
A segunda escolha aparece no cálculo da página. Ao paralelizar $n$ requisições, a latência é paga uma vez, mas a transmissão dos $n$ objetos continua disputando 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 entre São Paulo e 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: Vamos usar $\rho=\lambda/\mu$, $W_q=\rho/(\mu-\lambda)$, $W=1/(\mu-\lambda)$ e $L=\rho/(1-\rho)$. Para $\lambda=500$ pacotes/s,
\[\rho=\frac{500}{1000}=0{,}50,\qquad W_q=\frac{0{,}50}{1000-500}=0{,}001\ \text{s}=1\ \text{ms},\] \[W=\frac{1}{1000-500}=0{,}002\ \text{s}=2\ \text{ms},\qquad L=\frac{0{,}50}{1-0{,}50}=1.\]Para $\lambda=900$ pacotes/s, teremos
\[\rho=\frac{900}{1000}=0{,}90,\quad W_q=\frac{0{,}90}{100}=0{,}009\ \text{s}=9\ \text{ms},\quad W=\frac{1}{100}=10\ \text{ms},\quad L=\frac{0{,}90}{0{,}10}=9.\]Por fim, para $\lambda=990$ pacotes/s,
\[\rho=\frac{990}{1000}=0{,}99,\quad W_q=\frac{0{,}99}{10}=0{,}099\ \text{s}=99\ \text{ms},\quad W=\frac{1}{10}=100\ \text{ms},\quad L=\frac{0{,}99}{0{,}01}=99.\]A tabela reúne os três resultados para facilitar a comparação.
| $\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. Algoritmos de gerenciamento ativo de filas (AQM, de Active Queue Management), como CoDel e FQ-CoDel, procuram controlar o tempo de permanência na fila e sinalizar 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: Vamos chamar de $c_a$ o coeficiente de variação dos intervalos entre chegadas e de $c_s$ o coeficiente de variação dos tempos de serviço. Na aproximação de Kingman para uma fila G/G/1, a espera média contém o fator
\[K=\frac{c_a^2+c_s^2}{2}.\]No modelo M/M/1, as duas distribuições são exponenciais. Portanto, $c_a=c_s=1$ e
\[K_{\text{M/M/1}}=\frac{1^2+1^2}{2}=1.\]O enunciado mantém as demais hipóteses comparáveis, fixa $c_s=1$ e informa $c_a>1$. Substituindo,
\[K=\frac{c_a^2+1}{2}>\frac{1+1}{2}=1.\]Assim, a aproximação prevê espera média superior à referência M/M/1 na mesma utilização. A conclusão não é que toda fila real sempre espera mais. Se a combinação $(c_a^2+c_s^2)/2$ ficar abaixo de um, a direção se inverte. O modelo M/M/1 ensina a forma da curva sob hipóteses explícitas; não garante o valor de $p_{99}$, que precisa ser medido.
| 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. Um relógio inadequado, uma única repetição ou uma redução que conserva apenas a média pode produzir um número preciso sobre o experimento errado.
Comecemos pelo relógio. Uma duração exige um relógio monotônico, que não recue quando o sistema corrige a hora civil. Em C++23, vamos usar std::chrono::steady_clock. O system_clock continuará apropriado para registrar quando um evento ocorreu, mas não para medir quanto ele durou.
Depois, vamos separar aquecimento e medição. As primeiras execuções podem pagar falhas de cache, alocação de páginas e ajustes de frequência do processador. Elas preparam o estado que desejamos observar, mas não devem entrar silenciosamente na mesma distribuição das repetições cronometradas.
Em seguida, vamos guardar cada duração. Cronometrar mil repetições em bloco e dividir o total por mil conserva apenas a média. Ao medir cada repetição, preservamos a amostra necessária para calcular mediana, percentis e dispersão.
Por fim, vamos relatar a cauda junto da tendência central. Para calcular um percentil, não precisamos ordenar o vetor inteiro. O algoritmo std::nth_element posiciona a estatística de ordem desejada com complexidade linear média. Essa diferença importa quando a coleta contém milhões de observações.
O programa abaixo aplica essas quatro decisões a uma operação local. Também calcula percentis por interpolação linear e reproduz o estimador de jitter da RFC 3550 sobre os dados da Seção 6. Assim, temos valores conhecidos para conferir a implementação antes de confiar em medições dependentes da máquina.
O exemplo não mede a rede por conta própria. Para isso, precisaríamos acrescentar uma fonte de marcas de envio e chegada, declarar o ponto de observação e sincronizar os relógios quando as marcas viessem de máquinas diferentes. Sem essas definições, o código mediria alguma duração, mas ainda não saberíamos qual.
// latencia.cpp: latency statistics and the RFC 3550 jitter estimator.
// MSVC: cl /std:c++23preview /permissive- /Zc:__cplusplus /W4 /EHsc /O2 latencia.cpp
#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(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. Em particular, o $p_{95}$ volta a ser $87{,}80$ ms e o estimador termina em $4{,}25$ ms. Essa concordância não prova que toda a implementação esteja correta, mas verifica os dois caminhos contra cálculos independentes do programa. As três últimas linhas foram omitidas da saída porque dependem da máquina: elas contêm os 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, esconderia esse contrato dentro de um double. O tipo escolhido expõe o caminho de erro na assinatura. O programa exercita o caso degenerado de propósito, e a linha amostra vazia: amostra vazia confirma que ele foi tratado.
Ela recebe o vetor por valor, e isso também é deliberado. std::nth_element reordena o intervalo, mas uma função de consulta não deveria modificar silenciosamente a amostra do chamador. A cópia preserva esse contrato ao custo de memória e de uma possível alocação. Em uma coleta grande, poderíamos oferecer uma versão destrutiva explícita ou reutilizar uma área de trabalho, desde que a interface tornasse essa decisão visível.
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 10 vai formalizar a coleta, a redução e a anonimização desses dados, que é o que separa uma medição de um vazamento.
9. Da medição à decisão: um orçamento verificável
A Seção 8 entregou uma amostra, percentis e um método de cálculo. Esses números descrevem o que aconteceu, mas ainda não escolhem uma intervenção. Para chegar à decisão de engenharia, precisamos ligar cada mudança proposta à parcela de latência que ela realmente altera e estimar a redução antes de tocar no sistema.
Considere um serviço consumido de São Paulo, hospedado na Virgínia, com $300$ ms de tempo de resposta observado. Suponha que uma carga de $4$ KiB atravesse uma única vez um enlace de saída de $100$ Mbit/s. Como $L=4\times1024\times8=32\,768$ bits, o tempo de transmissão nesse enlace será
\[T_{\text{trans},100}=\frac{32\,768}{100\times10^6}=0{,}32768\ \text{ms}.\]Se a taxa do enlace subir para $1$ Gbit/s, a mesma transmissão passará a consumir
\[T_{\text{trans},1000}=\frac{32\,768}{10^9}=0{,}032768\ \text{ms}.\]A redução prevista será $0{,}32768-0{,}032768=0{,}294912$ ms. Em relação aos $300$ ms observados, isso representa $0{,}0983\%$, aproximadamente $0{,}1\%$. Para essa carga, nesse enlace e sem disputa, aumentar a taxa quase não move o tempo total. Se o objeto for maior ou se houver fila no enlace, precisaremos refazer a conta com o tamanho e a utilização medidos.
A próxima fronteira é o número de dependências sequenciais. Vamos chamar de $r$ o número de idas e voltas que precisam terminar antes de a resposta prosseguir. Usando o piso geográfico em fibra da Tabela 2, um orçamento inferior para a transação será dado por
\[T_{\text{total}} \ge r\,\text{RTT}_{\text{fibra}} + T_{\text{trans}} + T_{\text{proc}} + T_{\text{fila}}.\]Para a Virgínia, $\text{RTT}_{\text{fibra}}=76{,}6$ ms. Se a arquitetura exigir uma, duas ou três idas e voltas sequenciais, a propagação consumirá ao menos os valores da Tabela 4.
| Idas e voltas sequenciais | Piso de propagação | Parcela restante dos $300$ ms |
|---|---|---|
| $1$ | $76{,}6$ ms | $223{,}4$ ms |
| $2$ | $153{,}2$ ms | $146{,}8$ ms |
| $3$ | $229{,}8$ ms | $70{,}2$ ms |
Tabela 4: orçamento inferior de propagação para uma transação entre São Paulo e a Virgínia. A parcela restante ainda reúne transmissão, processamento, filas e o excesso da rota real sobre a geodésica.
A tabela não permite deduzir quantas viagens o serviço realiza. Ela mostra o que precisa ser medido. Uma linha do tempo da requisição deve separar a resolução de nomes, a abertura do transporte, a negociação criptográfica, o envio do pedido, o processamento remoto e a chegada da resposta. Se três dependências cruzarem o mesmo caminho em sequência, eliminar uma delas retira ao menos $76{,}6$ ms de propagação do orçamento idealizado. Isso é cerca de duzentas e sessenta vezes a redução de $0{,}294912$ ms calculada para o aumento de banda.
O contrato da medição vem antes da comparação. É preciso declarar o evento inicial, o evento final e o ponto de observação. Um tempo registrado dentro do servidor não inclui a rede até a usuária; um tempo observado no cliente inclui rede, processamento e qualquer espera anterior à resposta. Também precisamos nomear a população, a janela temporal, o tamanho da amostra e a estatística que representa o objetivo. Uma média inferior a $100$ ms não demonstra que o $p_{99}$ respeita o mesmo limite.
Depois do contrato, cada hipótese exige uma medida capaz de sustentá-la. Se a suspeita recair sobre transmissão ou fila no enlace, precisamos do tamanho dos objetos, da taxa efetiva, da utilização e do tempo de permanência na fila. Se recair sobre processamento, precisamos separar o tempo dentro do serviço e observar CPU, espera por armazenamento, bloqueios e concorrência. Se recair sobre viagens sequenciais, precisamos da linha do tempo que revele DNS, transporte, segurança e chamadas dependentes. O nome da parcela determina a instrumentação.
Por fim, a intervenção precisa nascer com um critério de sucesso. Antes da mudança, registramos a distribuição de referência; depois, repetimos a coleta na mesma fronteira e com carga comparável. A proposta estará demonstrada somente quando a parcela prevista diminuir e a estatística escolhida acompanhar essa redução sem deslocar o custo para CPU, memória, capacidade ou estabilidade.
Uma decisão de desempenho completa nomeia a parcela dominante, calcula a redução esperada, define como medi-la e declara qual outro recurso pode pagar a conta.
10. Conclusão
Este artigo não construiu nenhum protocolo. Ele construiu a régua com que vamos medir os quinze artigos seguintes.
Começamos pelo encapsulamento. Cada camada acrescenta um envelope, e sua eficiência só faz sentido quando declaramos qual mensagem está dentro de qual fronteira. Depois de fixar essa fronteira, conseguimos separar bytes úteis de cabeçalhos e escolher o tamanho da carga sem fingir que a sobrecarga desaparece.
Em seguida, decompusemos a latência em propagação, transmissão, processamento e fila. As quatro parcelas têm a mesma unidade, mas respondem a intervenções diferentes. Aumentar a taxa ajuda quando a transmissão ou a disputa pelo enlace domina. Não encurta a rota, não remove idas e voltas e não acelera, por si só, o processamento remoto.
A física nos deu um piso geográfico idealizado para o RTT. Esse piso não prevê a medição real, mas permite rejeitar números incompatíveis com a distância e o ponto de observação declarados. O produto banda-atraso acrescentou outra fronteira: para ocupar um caminho de alta capacidade, precisamos manter dados suficientes em voo.
A estatística mostrou por que uma única média não descreve a espera. Mediana, percentis altos, tamanho da amostra e método de quantil respondem a perguntas diferentes. Quando várias chamadas participam da mesma resposta, precisamos ainda declarar sua dependência, porque as caudas não se compõem apenas a partir dos percentis marginais.
Por fim, a fila M/M/1 revelou o mecanismo que acelera a espera perto da saturação. O valor de $80\%$ apareceu como consequência de um orçamento específico de $5$ ms, não como lei universal. Ao trocar o processo de chegadas, a distribuição do serviço ou o objetivo de latência, trocamos também o limite justificável.
Essas contas nos dão uma forma concreta de avaliar propostas de desempenho. A análise começa declarando a fronteira, fechando as unidades, comparando o número com o piso físico e identificando qual mecanismo causal deverá produzir a melhora prevista. Sem essa ligação, uma mudança pode consumir dinheiro ou estabilidade sem reduzir a parcela dominante.
A física fixa o piso. O que está acima do piso é uma 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 |
|---|---|---|
AQM |
Active Queue Management | Gerenciamento Ativo de Filas |
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 |
MAC |
Media Access Control | Controle de Acesso ao Meio |
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.
HOEILAND-JOERGENSEN, T.; MCKENNEY, P.; TAHT, D.; GETTYS, J.; DUMAZET, E. RFC 8290: The Flow Queue CoDel Packet Scheduler and Active Queue Management Algorithm. IETF, 2018. Disponível em: https://www.rfc-editor.org/rfc/rfc8290. Acesso em: 18 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. Disponível em: https://www.wiley.com/en-us/Queueing+Systems%2C+Volume+1%3A+Theory-p-9780471491101. Acesso em: 18 ago. 2026.
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. Microsoft C/C++ Language Conformance by Visual Studio Version. Microsoft Learn. Disponível em: https://learn.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=msvc-170. Acesso em: 18 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: 18 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. Disponível em: https://doi.org/10.1145/357401.357402. Acesso em: 18 ago. 2026.
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. Da Rede Local à Web: Dispositivos, Topologias e Serviços
- 3. Camada IP: Endereçamento, Sub-redes e Encaminhamento
- 4. Transporte: TCP, UDP e QUIC
(Updated: )