The attached patch delays the setting of TCP_NODELAY on client
connections
until the first time core_output_filter has to do a writev_it_all()
or emulate_sendfile().
My motivation for this is to work around the TCP_NODELAY/TCP_CORK
problem
in Linux 2.6. However, it also will save a couple of syscalls for
any request that
is handled with sendfile(2).
Note that there was an APR bug that caused TCP_NODELAY to be set on the
listener socket at startup as a side-effect of TCP_DEFER_ACCEPT being
set.
I just committed a fix for this. Without that fix, Linux 2.6 systems
using this httpd
patch will still exhibit the corking problem.
Can a couple of volunteers please test and/or review this patch? I'd
appreciate
a second opinion before I commit, given the subtlety of the NODELAY
and CORK
semantics on various platforms.
Thanks,
Brian
Index: server/core.c
===================================================================
--- server/core.c (revision 240169)
+++ server/core.c (working copy)
@@ -3827,25 +3827,6 @@
{
core_net_rec *net = apr_palloc(c->pool, sizeof(*net));
-#ifdef AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
- apr_status_t rv;
-
- /* The Nagle algorithm says that we should delay sending partial
- * packets in hopes of getting more data. We don't want to do
- * this; we are not telnet. There are bad interactions between
- * persistent connections and Nagle's algorithm that have very severe
- * performance penalties. (Failing to disable Nagle is not much of a
- * problem with simple HTTP.)
- */
- rv = apr_socket_opt_set(csd, APR_TCP_NODELAY, 1);
- if (rv != APR_SUCCESS && rv != APR_ENOTIMPL) {
- /* expected cause is that the client disconnected already,
- * hence the debug level
- */
- ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c,
- "apr_socket_opt_set(APR_TCP_NODELAY)");
- }
-#endif
net->c = c;
net->in_ctx = NULL;
net->out_ctx = NULL;
Index: server/listen.c
===================================================================
--- server/listen.c (revision 240164)
+++ server/listen.c (working copy)
@@ -126,10 +126,6 @@
}
}
-#if APR_TCP_NODELAY_INHERITED
- ap_sock_disable_nagle(s);
-#endif
-
if ((stat = apr_socket_bind(s, server->bind_addr)) != APR_SUCCESS) {
ap_log_perror(APLOG_MARK, APLOG_STARTUP|APLOG_CRIT, stat, p,
"make_sock: could not bind to address %pI",
Index: server/core_filters.c
===================================================================
--- server/core_filters.c (revision 240164)
+++ server/core_filters.c (working copy)
@@ -887,6 +887,10 @@
else
#endif
{
+#ifdef AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
+ (void)apr_socket_opt_set(net->client_socket,
+ APR_TCP_NODELAY, 1);
+#endif
rv = emulate_sendfile(net, fd, &hdtr, foffset, flen,
&bytes_sent);
}
@@ -898,7 +902,9 @@
}
else {
apr_size_t bytes_sent;
-
+#ifdef AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
+ (void)apr_socket_opt_set(net->client_socket, APR_TCP_NODELAY, 1);
+#endif
rv = writev_it_all(net->client_socket,
vec, nvec,
nbytes, &bytes_sent);