mysqljs / mysql

A pure node.js JavaScript Client implementing the MySQL protocol.
MIT License
18.27k stars 2.52k forks source link

Set TCP_NODELAY flag on TCP socket (disable Nagle's algorithm). #2560

Open vlasky opened 1 year ago

vlasky commented 1 year ago

This ensures packets are sent as soon as they're ready, lowering latency.

Other MySQL connectors/drivers used in other programming languages that I have looked at set this as a default.

A majority of HTTP clients/servers/proxies also set TCP_NODELAY as a default (e.g. curl, Nginx, HA_Proxy).

dougwilson commented 1 year ago

This change sounds good to me!

I wonder if there is any way we can add a test or not. No big deal if it's not possible or practical, just wqs thinking out loud.

P.S. Don't worry about the fail on the PR; the nvm project was broken for a while ans github added the broken version to their image. I guess for the time being I just need to add a step to update nvm 🙂

vlasky commented 1 year ago

When testing this enhancement I discovered that Linux does not provide an easy way to check the TCP socket options set on an open connection created by a running process.

To my surprise, the popular Linux utilities ss, lsof or netstat could not reveal the TCP socket options.

After doing some online research, I discovered that the only ways to check TCP socket options under Linux are to:

  1. Launch the executable using strace and examine the arguments of the system calls invoked on each TCP socket's file descriptor.

  2. Install the third-party kernel module knetstat that creates four new human-readable information files in /proc/net: tcpstat, tcp6stat, udpstat and udp6stat

I was not able to use knetstat because I'm running Ubuntu Linux 22.04 within WSL2 under Windows 10. This WSL2-specific Linux distribution does not come with kernel module support or even the kernel headers that would allow knetstat to be compiled!

If it's deemed necessary, it would be theoretically be possible to make an automated test for this in a docker container by launching the test program using strace and grepping the output. The relevant lines would look something like this:

socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 24
setsockopt(24, SOL_TCP, TCP_NODELAY, [1], 4) = 0

The allocated file handle (24) may of course be different.

If using knetstat, the test environment would require a virtual machine - a normal docker container (as far as I know) does not let you load kernel modules.

And yes, I am also thinking out loud :-)