[HN Gopher] It's Always TCP_NODELAY
       ___________________________________________________________________
        
       It's Always TCP_NODELAY
        
       Author : eieio
       Score  : 24 points
       Date   : 2025-12-22 21:09 UTC (1 hours ago)
        
 (HTM) web link (brooker.co.za)
 (TXT) w3m dump (brooker.co.za)
        
       | eieio wrote:
       | I found this article while debugging some networking delays for a
       | game that I'm working on.
       | 
       | It turns out that in my case it _wasn 't_ TCP_NODELAY - my
       | backend is written in go, and go sets TCP_NODELAY by default!
       | 
       | But I still found the article - and in particular Nagle's
       | acknowledgement of the issues! - to be interesting.
       | 
       | There's a discussion from two years ago here:
       | https://news.ycombinator.com/item?id=40310896 - but I figured
       | it'd been long enough that others might be interested in giving
       | this a read too.
        
       | kazinator wrote:
       | > _The bigger problem is that TCP_QUICKACK doesn't fix the
       | fundamental problem of the kernel hanging on to data longer than
       | my program wants it to._
       | 
       | Well, of course not; it tries to reduce the problem of your
       | kernel hanging on to an ack (or genearting an ack) longer than
       | you would like. That pertains to received data. If the remote end
       | is sending you data, and is paused due to filling its buffers due
       | to not getting an ack from you, it behooves you to send an ack
       | ASAP.
       | 
       | The original Berkeley Unix implementation of TCP/IP, I seem to
       | recall, had a single global 500 ms timer for sending out acks. So
       | when your TCP connection received new data eligible for acking,
       | it could be as long as 500 ms before the ack was sent. If we
       | reframe that in modern realities, we can imagine every other
       | delay is negligible, and data is coming at the line rate of a
       | multi gigabit connection, 500 ms represents a lot of
       | unacknowledged bits.
       | 
       | Delayed acks are similar to Nagle in spirit in that they promote
       | coalescing at the possible cost of performance. Under the
       | assumption that the TCP connection is bidirectional and "chatty"
       | (so that even when the bulk of the data transfer is happening in
       | one direction, there are application-level messages in the other
       | direction) the delayed ack creates opportunities for the TCP ACK
       | to be piggy backed on a data transfer. A TCP segment carrying no
       | data, only an ACK, is prevented.
       | 
       | As far as portability of TCP_QUICKACK goes, in C code it is as
       | simple as #ifdef TCP_QUICKACK. If the constant exists, use it.
       | Otherwise out of luck. If you're in another language, you have to
       | to through some hoops depending on whether the network-related
       | run time exposes nonportable options in a way you can test, or
       | whether you are on your own.
        
       | anonymousiam wrote:
       | The Nagle algorithm was created back in the day of multi-point
       | networking. Multiple hosts were all tied to the same
       | communications (Ethernet) channel, so they would use CSMA
       | (https://en.wikipedia.org/wiki/Carrier-sense_multiple_access_...)
       | to avoid collisions. CSMA is no longer necessary on Ethernet
       | today because all modern connections are point-to-point with only
       | two hosts per channel. In fact, most modern (Gigabit+) Ethernet
       | connections have both ends both transmitting and receiving AT THE
       | SAME TIME ON THE SAME WIRES. A hybrid is used on the PHY at each
       | end to subtract what is being transmitted from what is being
       | received.
       | 
       | Dumping the Nagle algorithm (by setting TCP_NODELAY) almost
       | always makes sense and should be enabled by default.
        
       ___________________________________________________________________
       (page generated 2025-12-22 23:00 UTC)