You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When running touche with a client that supports connection reuse on Linux, responses after the first response on the same connection that are larger than 1KB experience a 40 millisecond delay:
$ time curl -s http://localhost:4444 http://localhost:4444 > /dev/null
real 0m0.047s
This delay occurs due to an interaction between std::io::copy, Nagle's algorithm, and TCP delayed ACK:
touche attempts to buffer writes using BufWriter. However, when a fixed-length response is larger than 1024 bytes, touche writes it using std::io::copy. The problem with this is that the implementation of copy has a specialization for BufWriter that allows it to reuse the writer's internal buffer space. In certain cases, this specialization appears to flush the buffer before and after performing the copy. This results in the response headers and body being sent in at least two separate TCP segments.
TCP delayed ACK causes the client to wait before acknowledging the first segment, because it is smaller than the maximum segment size.
Nagle's algorithm causes the server to wait before sending the second segment, because the first segment is unacknowledged.
Thanks for the thoroughly investigation! I will take a better look into this too, but that was totally unexpected behavior. And yeah, maybe we should disable Nagle's algorithm by default and expose a flag if the user doesn't want that.
When running touche with a client that supports connection reuse on Linux, responses after the first response on the same connection that are larger than 1KB experience a 40 millisecond delay:
This delay occurs due to an interaction between
std::io::copy
, Nagle's algorithm, and TCP delayed ACK:BufWriter
. However, when a fixed-length response is larger than 1024 bytes, touche writes it usingstd::io::copy
. The problem with this is that the implementation ofcopy
has a specialization forBufWriter
that allows it to reuse the writer's internal buffer space. In certain cases, this specialization appears to flush the buffer before and after performing the copy. This results in the response headers and body being sent in at least two separate TCP segments.I think the first response on a connection is unaffected because Linux always acknowledges the first data segment immediately.
This could be fixed in touche by either:
std::io::copy
to ensure that theBufWriter
is not flushed unexpectedly.TcpStream::set_nodelay
.The text was updated successfully, but these errors were encountered: