Philip Gladstone wrote:
I noticed that the performance of TransmitFile (used when EnableSendFile On on Windows platforms) was significantly worse than EnableSendFile Off.
It turns out that the way that TransmitFile is called is *without* the TF_WRITE_BEHIND flag. This means that TransmitFile does not complete (or rather that the socket is not signalled) until *all the data* has been ack'ed by the client. Windows clients send acks (roughly) every other data packet, or after a 200ms timeout. Thus, about half the time, the TransmitFile does not complete until this 200ms timeout has triggered.
This reduces the throughput on high speed networks significantly. On a 100Mbit LAN, the throughput drops from 11MBytes/sec to around 2.5MBytes/sec.
My question is: is there a good reason that the TF_WRITE_BEHIND flag is not being used?
Try applying this patch to apr and let me know how it works.
Bill
$ cvs diff -u sendrecv.c
Index: sendrecv.c
===================================================================
RCS file: /home/cvs/apr/network_io/win32/sendrecv.c,v
retrieving revision 1.64.2.1
diff -u -r1.64.2.1 sendrecv.c
--- sendrecv.c 13 Feb 2004 09:33:51 -0000 1.64.2.1
+++ sendrecv.c 12 Apr 2004 16:14:17 -0000
@@ -237,7 +237,7 @@
apr_status_t status = APR_SUCCESS;
apr_ssize_t rv;
apr_off_t curoff = *offset;
- DWORD dwFlags = 0;
+ DWORD dwFlags = TF_WRITE_BEHIND;
DWORD nbytes;
OVERLAPPED overlapped;
TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL;
@@ -323,6 +323,7 @@
/* Disconnect the socket after last send */
if ((flags & APR_SENDFILE_DISCONNECT_SOCKET)
&& !sendv_trailers) {
+ dwFlags = 0;
dwFlags |= TF_REUSE_SOCKET;
dwFlags |= TF_DISCONNECT;
disconnected = 1;
@@ -333,7 +334,6 @@
#if APR_HAS_LARGE_FILES
overlapped.OffsetHigh = (DWORD)(curoff >> 32);
#endif
- /* XXX BoundsChecker claims dwFlags must not be zero. */
rv = TransmitFile(sock->socketdes, /* socket */
file->filehand, /* open file descriptor of the file to be
sent */
nbytes, /* number of bytes to send. 0=send all */