Sysctl knob(s) to set TCP 'nagle' time-out?

Stefan Eßer se at freebsd.org
Mon Jun 23 10:23:08 UTC 2008


Matthew Dillon wrote:
>     In anycase, the usual solution is to disable Nagle rather then mess
>     with delayed acks.  What we need is a new Nagle that understands the
>     new reality for interactive connections... something that doesn't break
>     performance in the 'server in the middle' data relaying case.

One possibility I see is a statistic about DelACKs per TCP connection,
counting those that were rightfully delayed (with hindsight). I.e.,
if an ACK is delayed, but there was no chance to piggy-back it or to
combine it with another ACK, it could have been sent without delay.
Only those delayed ACKs that reduce load are "good", all others cause
additional state to be maintained and may increase latencies for no
good reason.

Therefore, I thought about starting with Nagle enabled, but give up
on delaying ACKs, when doing so is found to be ineffective.

The only problem with this approach is that once TCP_NODELAY is
implicitly set due to measured behavior of the communication, a
situation that would benefit from delayed ACKs can no longer be
detected. (Well, you could measure the delay between an ACK and
the next data sent to the same destination; disable TCP_NODELAY
if ACKs could have been piggy-backed on data packets without too
much delay. May be we could really have TCP auto-tune with respect
to use of delayed ACKs ...

I had suggested this years back, when the issue was discussed, but
consensus was, that you should just set TCP_NODELAY. But automatic
adjustment could also (implicitly) take RTT, window size into
consideration. And to me, automatic setting of TCP_NODELAY seems
more useful than automatic clearing (after delayed ACKs had been
found to be of no use for a window of say 8 or 16 ACKs).

The implementation would be quite simple: Whenever a delayed ACK
is sent, check whether it is sent on its own (bad) or whether it
could be piggy-backed (good). If, say, 7 of 8 delayed ACKs had to
be sent as ACK-only packets, anyway, set TCP_NODELAY and do not
bother to keep on deciding whether delayed ACKs had become useful
in a different phase of the communication. If you want to be able
to automatically disable TCP_NODELAY, then just set a time-stamp
whenever an ACK is sent and when the next data is sent through
this same socket, check whether delaying the ACK had allowed to
send it with that data packet (i.e. the delay was less than the
maximum hold time of the delayed ACK). If it had been beneficial
to delay ACKs (say 3 out of a window of 4) then clear TCP_NODELAY.

I have no idea, whether SMP locking would be problematic, but I
guess the checks and counter updates could be put in sections
that are appropriately locked, anyway.

Regards, STefan


More information about the freebsd-stable mailing list