Somewhat related, from 3 years ago. Unfortunately, original blog is gone. "Golang disables Nagle's Algorithm by default" 1. https://news.ycombinator.com/item?id=34179426
It's Always TCP_NODELAY
111–120 of 186 posts
Re: It's Always TCP_NODELAY
#112Re: It's Always TCP_NODELAY
#113Earlier quoted context omitted.
What did you still need to connect with 10mbit half duplex in 2014? I had gigabit to the desktop for a relatively small company in 2007, by 2014 10mb was pretty dead unless you had something Really Interesting connected....
There's plenty of use cases for small things which don't need any sorts of speeds, where you might as well have used a 115200 baud serial connection but ethernet is more useful. Designing electronics for 10Mbit/s is infinitely easier and cheaper than designing electronics for 100Mbit/s, so if you don't need 100Mbit/s, why would you spend the extra effort and expense?
Re: It's Always TCP_NODELAY
#114Earlier quoted context omitted.
Nagle is quite sensible when your application isn't taking any care to create sensibly-sized packets, and isn't so sensitive to latency. It avoids creating stupidly small packets unless your network is fast enough to handle them.
At this point, this is an application level problem and not something the kernel should be silently doing for you IMO. An option for legacy systems or known problematic hosts fine, but off by default and probably not a per SOCKOPT. Every modern language has buffers in their stdlib. Anyone writing character at a time to the wire lazily or unintentionally should fix their application.
Re: It's Always TCP_NODELAY
#115Earlier quoted context omitted.
Yeah, I’ve always felt that the stream API is a leaky abstraction for providing access to networking. I understand the attraction of making network I/O look like local file access given the philosophy of UNIX. The API should have been message oriented from the start. This would avoid having the network stack try to compensate for the behavior of the application layer. Then Nagel’s or something like it would just be a…
the whole point of TCP is that it is a stream of bytes, not of messages. The problem is that this is not in practice quite what most applications need, but the Internet evolved towards UDP and TCP only. So you can have message-based if you want, but then you have to do sequencing, gap filling or flow control yourself, or you can have the overkill reliable byte stream with limited control or visibility at the applicat…
Re: It's Always TCP_NODELAY
#116Earlier quoted context omitted.
There is also a good write-up [0] by Julia Evans. We ran into this with DICOM storescp, which is a chatty protocol and TCP_NODELAY=1 makes the throughput significantly better. Since DICOM is often used in a LAN, that default just makes it unnecessarily worse. [0]: https://jvns.ca/blog/2015/11/21/why-you-should-understand-a-... [1]: https://news.ycombinator.com/item?id=10607422
I wonder how this fix could be implemented without source code access. Suppose an old ct scanner is clogging up the network.
Re: It's Always TCP_NODELAY
#117Dunno if it helps but it helps me feel better.
What speeds up browsing the most though IMO is running your own DNS resolver, null routing a big part of the Internet, firewalling off entire countries (no really I don't need anything from North Korea, China or Russia for example), and then on top of that running dnsmasq locally.
I run the unbound DNS (on a little Pi so it's on 24/7) with gigantic killfiles, then I use 1.1.1.3 on top of that (CloudFlare's DNS that filters out known porn and known malware: yes, it's CloudFlare and, yes, I own shares of NET).
Some sites complain I use an "ad blocker" but it's really just null routing a big chunk of the interwebz.
That and LD_PRELOAD a lib with TCP_NODELAY: life is fast and good. Very low latency.
Re: It's Always TCP_NODELAY
#118Earlier quoted context omitted.
Just to add, ethernet uses csma/cd, WiFi uses csma/ca. Upgraded our DC switches to new ones around 2014 and needed to keep a few old ones because the new ones didn't support 10Mbit half duplex.
Thanks for the clarification. They're so close to being the same thing that I always call it CSMA/CD. Avoiding a collision is far more preferable than just detecting one. Yeah, many enterprise switches don't even support 100Base-T or 10Base-T anymore. I've had to daisy chain an old switch that supports 100Base-T onto a modern one a few times myself. If you drop 10/100 support, you can also drop HD (simplex) support.…
Re: It's Always TCP_NODELAY
#119Wildly, the Polish word "nagle" (pronounced differently) means "suddenly" or "all at once", which is just astonishingly apropos for what I'm almost certain is pure coincidence.
Re: It's Always TCP_NODELAY
#120The core issue with Nagle’s algorithm (TCP_NODELAY off) is its interaction with TCP Delayed ACK. Nagle prevents sending small packets if an ACK is outstanding, while the receiver delays that ACK to piggyback it on a response. When both are active, you get a 200ms "deadlock" where the sender waits for an ACK and the receiver waits for more data. This is catastrophic for latency-sensitive applications like gaming, SSH, or high-frequency RPCs.
In modern times, the bandwidth saved by Nagle is rarely worth the latency cost. You should almost always set TCP_NODELAY = 1 for any interactive or request-response protocol. The "problem" only shifts to the application layer: if you disable Nagle and then perform many small write() calls (like writing a single byte at a time), you will flood the network with tiny, inefficient packets.
Proper usage means disabling Nagle at the socket level but managing your own buffering in user-space. Use a buffered writer to assemble a logical message into a single memory buffer, then send it with one system call. This ensures your data is dispatched immediately without the overhead of thousands of tiny headers. Check the Linux tcp(7) man page for implementation details; it is the definitive reference for these behaviors.