C'est une optimisation, donc comme toute optimisation :
- Ne l'utilisez pas
- Attendez que les performances deviennent un problème, puis après avoir déterminé que la latence du socket en est définitivement la cause, et les tests prouvent que cela résoudra définitivement le problème, ET c'est le moyen le plus simple de le résoudre, faites-le.
Fondamentalement, le but est d'éviter d'avoir à envoyer plusieurs trames là où une seule trame peut être utilisée, avec sendfile() et ses amis.
Ainsi par exemple, dans un serveur web, vous envoyez les en-têtes suivis du contenu du fichier, les en-têtes seront assemblés en mémoire, le fichier sera alors envoyé directement par le noyau. TCP_CORK vous permet d'envoyer les en-têtes et le début du fichier dans une seule trame, même avec TCP_NODELAY, ce qui entraînerait autrement l'envoi immédiat du premier bloc.
TCP_NODELAY
Utilisé pour désactiver l'algorithme de Nagle afin d'améliorer les réseaux TCP/IP et de réduire le nombre de paquets en attendant qu'un accusé de réception des données précédemment envoyées soit reçu pour envoyer les paquets accumulés.
//Depuis le manuel tcp(7) :
TCP_CORK
(ou TCP_NOPUSH
sous FreeBSD)
S'il est défini, n'envoie pas de trames partielles. Toutes les trames partielles en file d'attente sont envoyées lorsque l'option est à nouveau désactivée. Ceci est utile pour ajouter des en-têtes avant d'appeler sendfile(2)
, ou pour l'optimisation du débit. Tel qu'il est actuellement mis en œuvre, il existe un plafond de 200 millisecondes sur le temps pendant lequel la sortie est bouchée par TCP_CORK
. Si ce plafond est atteint, les données en file d'attente sont automatiquement transmises . Cette option peut être combinée avec TCP_NODELAY
uniquement depuis Linux 2.5.71. Cette option ne doit pas être utilisée dans du code destiné à être portable.
Tout d'abord, tous les deux ne désactivent pas l'algorithme de Nagle.
L'algorithme de Nagle sert à réduire davantage le nombre de petits paquets réseau dans le câble. L'algorithme est :si les données sont inférieures à une limite (généralement MSS), attendez jusqu'à la réception de l'ACK pour les paquets précédemment envoyés et, en attendant, accumulez les données de l'utilisateur. Envoyez ensuite les données accumulées.
if [ data > MSS ]
send(data)
else
wait until ACK for previously sent data and accumulate data in send buffer (data)
And after receiving the ACK send(data)
Cela aidera dans des applications comme telnet. Cependant, attendre l'ACK peut augmenter la latence lors de l'envoi de données en continu. De plus, si le récepteur implémente la "politique d'accusé de réception retardé", cela provoquera une situation de blocage temporaire. Dans de tels cas, désactiver l'algorithme de Nagle est une meilleure option.
TCP_NODELAY est donc utilisé pour désactiver l'algorithme de Nagle.
TCP_CORK accumule agressivement les données. Si TCP_CORK est activé dans un socket, il n'enverra pas de données tant que le tampon ne sera pas rempli jusqu'à une limite fixe. Semblable à l'algorithme de Nagle, il accumule également les données de l'utilisateur, mais jusqu'à ce que le tampon se remplisse jusqu'à une limite fixe, pas avant de recevoir ACK. Cela sera utile lors de l'envoi de plusieurs blocs de données. Mais vous devez être plus prudent lorsque vous utilisez TCP_CORK.
Jusqu'au noyau 2.6, ces deux options s'excluent mutuellement. Mais dans le noyau ultérieur, les deux peuvent exister ensemble. Dans ce cas, TCP_CORK aura plus de préférence.
Réf :
- http://baus.net/on-tcp_cork/
- http://ccr.sigcomm.org/archive/2001/jan01/ccr-200101-mogul.pdf