El algoritmo de Nagle es un medio para mejorar la eficiencia de las redes TCP/IP al reducir la cantidad de paquetes que deben enviarse a través de la red. Fue definido por John Nagle mientras trabajaba para Ford Aerospace . Se publicó en 1984 como una solicitud de comentarios (RFC) con el título Control de congestión en redes IP/TCP en RFC 896.
El RFC describe lo que Nagle llama el "problema de los paquetes pequeños", en el que una aplicación emite repetidamente datos en pequeños fragmentos, con frecuencia de solo 1 byte de tamaño. Dado que los paquetes TCP tienen un encabezado de 40 bytes (20 bytes para TCP, 20 bytes para IPv4 ), esto da como resultado un paquete de 41 bytes para 1 byte de información útil, una sobrecarga enorme. Esta situación ocurre a menudo en sesiones Telnet , donde la mayoría de las pulsaciones de teclas generan un solo byte de datos que se transmite inmediatamente. Peor aún, en enlaces lentos, muchos de estos paquetes pueden estar en tránsito al mismo tiempo, lo que potencialmente conduce a un colapso por congestión .
El algoritmo de Nagle funciona combinando una serie de pequeños mensajes salientes y enviándolos todos a la vez. En concreto, mientras haya un paquete enviado para el que el remitente no haya recibido confirmación, el remitente debe seguir almacenando en búfer su salida hasta que tenga la salida de un paquete completo, lo que permite enviar toda la salida a la vez.
El RFC define el algoritmo como
inhibir el envío de nuevos segmentos TCP cuando llegan nuevos datos salientes del usuario si algún dato transmitido previamente en la conexión permanece sin reconocer.
Donde MSS es el tamaño máximo del segmento , el segmento más grande que se puede enviar en esta conexión, y el tamaño de la ventana es la ventana actualmente aceptable de datos no reconocidos, esto se puede escribir en pseudocódigo como [ cita requerida ]
Si hay nuevos datos para enviar , entonces si el tamaño de la ventana es ≥ MSS y los datos disponibles son ≥ MSS , entonces Envía el segmento MSS completo ahora De lo contrario, si todavía hay datos no confirmados en la tubería , entonces poner en cola los datos en el búfer hasta que se reciba un acuse de recibo demás enviar datos inmediatamente fin si fin si fin si
Este algoritmo interactúa mal con los reconocimientos retrasados de TCP (ACK retrasado), una característica introducida en TCP aproximadamente al mismo tiempo a principios de los años 1980, pero por un grupo diferente. Con ambos algoritmos habilitados, las aplicaciones que realizan dos escrituras sucesivas en una conexión TCP, seguidas de una lectura que no se completará hasta que los datos de la segunda escritura hayan llegado al destino, experimentan un retraso constante de hasta 500 milisegundos, el " retraso de ACK ". Se recomienda deshabilitar cualquiera de los dos, aunque tradicionalmente es más fácil deshabilitar Nagle, ya que dicho interruptor ya existe para aplicaciones en tiempo real.
Una solución recomendada por Nagle, que evita que el algoritmo envíe paquetes prematuros, es almacenar en búfer las escrituras de la aplicación y luego vaciar el búfer: [1]
La solución a nivel de usuario es evitar secuencias de escritura-escritura-lectura en los sockets. Escritura-lectura-escritura-lectura está bien. Escritura-escritura-escritura está bien. Pero escritura-escritura-lectura es letal. Por lo tanto, si puede, almacene en búfer sus pequeñas escrituras en TCP y envíelas todas a la vez. Usar el paquete de E/S estándar de UNIX y vaciar la escritura antes de cada lectura suele funcionar.
Nagle considera que los ACK retrasados son una "mala idea", ya que la capa de aplicación no suele responder dentro de la ventana de retraso (lo que permitiría que el ACK se combinara con el paquete de respuesta). [2] Para los casos de uso típicos (no en tiempo real), recomienda deshabilitar el ACK retrasado en lugar de deshabilitar su algoritmo, ya que los ACK "rápidos" no incurren en tanta sobrecarga como muchos paquetes pequeños para la misma mejora en el tiempo de ida y vuelta. [3]
Las implementaciones de TCP suelen proporcionar a las aplicaciones una interfaz para desactivar el algoritmo de Nagle. Esto se suele llamar TCP_NODELAY
opción. En Microsoft Windows, el TcpNoDelay
modificador de registro decide el valor predeterminado. TCP_NODELAY
está presente desde la pila TCP/IP en 4.2BSD de 1983, una pila con muchos descendientes. [4]
La interfaz para desactivar el ACK retrasado no es uniforme entre los distintos sistemas. La TCP_QUICKACK
opción está disponible en Linux desde 2001 (2.4.4) y posiblemente en Windows, donde la interfaz oficial es SIO_TCP_SET_ACK_FREQUENCY
. [5]
La configuración TcpAckFrequency
en 1 en el registro de Windows desactiva el ACK retrasado de manera predeterminada. [6] En FreeBSD, la entrada sysctl net.inet.tcp.delayed_ack controla el comportamiento predeterminado. [4] No existe tal modificador en Linux. [7]
La interacción entre el ACK retrasado y Nagle también se extiende a escrituras más grandes. Si los datos en una sola escritura abarcan 2 n paquetes, donde hay 2 n -1 segmentos TCP de tamaño completo seguidos de un segmento TCP parcial, el algoritmo Nagle original retendría el último paquete, esperando a que se envíen más datos (para completar el paquete), o el ACK para el paquete anterior (lo que indica que todos los paquetes anteriores han abandonado la red). Un ACK retrasado, nuevamente, agregaría un máximo de 500 ms antes de que se envíe el último paquete. [8] Este comportamiento limita el rendimiento para el protocolo de aplicación de solicitud-respuesta de detención y espera no segmentado, como HTTP con conexión persistente. [9]
La modificación de Minshall al algoritmo de Nagle hace que el algoritmo siempre envíe si el último paquete es de tamaño completo , y solo espera un acuse de recibo cuando el último paquete es parcial. El objetivo era debilitar el incentivo para deshabilitar Nagle al ocuparse de esta penalización por escritura de gran tamaño. [10] Nuevamente, deshabilitar el ACK retrasado en el extremo receptor eliminaría el problema por completo.
Las aplicaciones que esperan respuestas en tiempo real y baja latencia pueden reaccionar mal con el algoritmo de Nagle. Aplicaciones como los videojuegos multijugador en red o el movimiento del ratón en un sistema operativo controlado de forma remota, esperan que las acciones se envíen de forma inmediata, mientras que el algoritmo retrasa deliberadamente la transmisión, aumentando la eficiencia del ancho de banda a expensas de la latencia unidireccional . [3] Por esta razón, las aplicaciones con transmisiones sensibles al tiempo y de bajo ancho de banda suelen utilizar TCP_NODELAY
el método de omitir el retraso de ACK retardado por Nagle. [11]
Otra opción es utilizar UDP .
La mayoría de los sistemas operativos modernos implementan los algoritmos de Nagle. En AIX, [12] y Windows, está habilitado de forma predeterminada y se puede deshabilitar por socket mediante la TCP_NODELAY
opción.
[...] Uno de los pocos casos legítimos para desactivar el algoritmo de Nagle es para un juego de FPS que se ejecuta en la red. Allí, la latencia unidireccional importa; hacer que tus tiros y movimientos lleguen al servidor antes que los otros jugadores afecta la jugabilidad.