gvanem / Watt-32

Watt-32 TCP/IP library and samples.
https://www.watt-32.net/
18 stars 8 forks source link

Improve PUSH-bit / flush logic #105

Closed jwt27 closed 7 months ago

jwt27 commented 7 months ago

This patch reduces the number of segments sent with PUSH bit, so that a receiver is more inclined to use delayed-ACK.

Logic:

In addition, we can borrow MSG_MORE from Linux to give the BSD interface more control over this. This is then also used internally to control flushing of multiple iovecs in sendmsg()/writev_s().

gvanem commented 7 months ago

In addition, we can borrow MSG_MORE from Linux to give the BSD interface more control over this.

Nice. I had never seen this MSG_MORE flag before.

jwt27 commented 7 months ago

It should make things a bit more efficient, especially with many small buffers in writev_s()/sendmsg(). For example, Beast does this with HTTP header lines, and right now Watt-32 will send each line in a separate packet (but this is also partly due to broken Nagle mode, fixed by #103).

gvanem commented 7 months ago

For example, Beast does this with HTTP header lines, ...

You mean Boost.Beast?

jwt27 commented 7 months ago

For example, Beast does this with HTTP header lines, ...

You mean Boost.Beast?

Yes, I use it for a Websocket server. Also thinking about it some more, it's not so much the incorrect tx_datalen used, but more that we do tcp_tick() for every iovec in transmit(). So each line gets ACKed almost immediately.

jwt27 commented 7 months ago

This all works now, as far as I can tell. Transmit rate on a 10MB file is 2000 - 2200 KB/s.

One remaining issue is that _tcp_send() can only see the TX buffer, it doesn't know if more data is still coming. So with a small TX buffer (<= receiver's window), if you send a large chunk with sock_write(), the PUSH flag is still set more often than strictly necessary. I don't see an easy solution for that, but it's not a deal breaker.

gvanem commented 7 months ago

Merged and thanks a bunch again. I'll use Lynx to test this.