This patch implements SendBufferSize, a directive to set the size of the TCP send-buffer. On many systems the default send-buffer size is too small to support full-rate transfer over high bandwidth-delay-product networks (such as cross-US Internet traffic). For example, a 100ms round-trip time (typical cross-US latency) and a 4kB default buffer size (common to many OSes such as SunOS) limit transfer rate to 40kB/s. Much better cross-US transfer rates are possible between well-connected hosts if the send buffer size is increased. A patch at [this patch] implements the SendBufferSize directive to allow Apache to have a configurable buffer size. A complete description of this directive is in the file send_buffer_size.html which accompanies the patch. For a pointer to other patches, see . For descriptions of the problems motivating these patches, see . -John Heidemann USC/ISI 28-Oct-96 ---------------------------------------------------------------------- Index: send_buffer_size.html diff -c /dev/null lsam/apache/src/send_buffer_size.html:1.2 *** /dev/null Mon Oct 28 15:27:27 1996 --- lsam/apache/src/send_buffer_size.html Mon Oct 28 15:24:36 1996 *************** *** 0 **** --- 1,33 ---- + + + +

SendBufferSize directive

+ + Syntax: SendBufferSize number
+ Default: system dependent, often 4kB to 16kB
+ Context: server config
+ Status: core

+ + The SendBufferSize directive sets the size of the TCP send buffer + as specified in bytes. + + To send data over high bandwidth-delay connections at full + speed we must the TCP window to open wide enough to keep the + pipe full. Default the default window size on many systems + is only 4kB. Cross-country WAN connections of 100ms + at 1Mb/s are not impossible for well connected sites in 1995. + If we assume 100ms cross-country latency, + a 4kB buffer limits throughput to 40kB/s. + + The default is system dependent, often 4kB to 16kB. + Setting it larger than the default consumes more kernel memory + per connection but allows better performance for wide-area connections. + A value of 16384 is probably good for most networks; + 8kB is good if you're connected by less than a T1 link. + + This value is Apache-wide, not per-virtual server. + + Index: http_config.c diff -c lsam/apache/src/http_config.c:1.1.1.2 lsam/apache/src/http_config.c:1.2 *** lsam/apache/src/http_config.c:1.1.1.2 Thu Jul 18 10:13:38 1996 --- lsam/apache/src/http_config.c Fri Oct 25 16:39:48 1996 *************** *** 705,710 **** --- 705,715 ---- if (virt->keep_alive == -1) virt->keep_alive = main_server->keep_alive; + + #ifdef ISI_SET_SNDBUF + if (virt->send_buffer_size == 0) + virt->send_buffer_size = main_server->send_buffer_size; + #endif /* ISI_SET_SNDBUF */ } } Index: http_core.c diff -c lsam/apache/src/http_core.c:1.3 lsam/apache/src/http_core.c:1.4 *** lsam/apache/src/http_core.c:1.3 Thu Jul 18 11:12:34 1996 --- lsam/apache/src/http_core.c Fri Oct 25 16:39:49 1996 *************** *** 637,642 **** --- 637,653 ---- return NULL; } + #ifdef ISI_SET_SNDBUF + char *set_send_buffer_size (cmd_parms *cmd, void *dummy, char *arg) { + int s = atoi (arg); + if (s < 512 && s != 0) { + return "SendBufferSize must be >= 512 bytes, or 0 for system default."; + } + cmd->server->send_buffer_size = s; + return NULL; + } + #endif /* ISI_SET_SNDBUF */ + char *set_user (cmd_parms *cmd, void *dummy, char *arg) { user_name = pstrdup (cmd->pool, arg); user_id = uname2id (user_name); *************** *** 847,852 **** --- 858,866 ---- "'*', a numeric IP address, or the name of a host with a unique IP address"}, { "Listen", set_listener, NULL, RSRC_CONF, TAKE1, "a port number or a numeric IP address and a port number"}, + #ifdef ISI_SET_SNDBUF + { "SendBufferSize", set_send_buffer_size, NULL, RSRC_CONF, TAKE1, "send buffer size in bytes"}, + #endif /* ISI_SET_SNDBUF */ { "", end_virtualhost_section, NULL, RSRC_CONF, NO_ARGS, NULL }, { NULL }, Index: http_main.c diff -c lsam/apache/src/http_main.c:1.7 lsam/apache/src/http_main.c:1.9 *** lsam/apache/src/http_main.c:1.7 Thu Jul 18 18:14:36 1996 --- lsam/apache/src/http_main.c Mon Oct 28 15:24:34 1996 *************** *** 1394,1399 **** --- 1394,1428 ---- } #endif /* NEED_LINGER */ + #ifdef ISI_SET_SNDBUF + /* + * To send data over high bandwidth-delay connections at full + * speed we must the TCP window to open wide enough to keep the + * pipe full. Default the default window size on many systems + * is only 4kB. Cross-country WAN connections of 100ms + * at 1Mb/s are not impossible for well connected sites in 1995. + * If we assume 100ms cross-country latency, + * a 4kB buffer limits throughput to 40kB/s. + * + * To avoid this problem I've added the SendBufferSize directive + * to allow the web master to configure send buffer size. + * + * The trade-off of larger buffers is that more kernel memory + * is consumed. YMMV, know your customers and your network! + * + * -John Heidemann 25-Oct-96 + * + * + * If no size is specified, use the kernel default. + */ + if (server_conf->send_buffer_size) { + if((setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&server_conf->send_buffer_size, sizeof(int))) < 0) { + perror("setsockopt(SO_SNDBUF), using default buffer size"); + /* Fail soft. */ + } + } + #endif /* ISI_SET_SNDBUF */ + if(bind(s, (struct sockaddr *)server,sizeof(struct sockaddr_in)) == -1) { perror("bind"); Index: httpd.h diff -c lsam/apache/src/httpd.h:1.5 lsam/apache/src/httpd.h:1.6 *** lsam/apache/src/httpd.h:1.5 Thu Jul 18 11:12:44 1996 --- lsam/apache/src/httpd.h Fri Oct 25 16:39:54 1996 *************** *** 500,505 **** --- 500,508 ---- int timeout; /* Timeout, in seconds, before we give up */ int keep_alive_timeout; /* Seconds we'll wait for another request */ int keep_alive; /* Maximum requests per connection */ + #ifdef ISI_SET_SNDBUF + int send_buffer_size; /* size of TCP send buffer (in bytes) */ + #endif /* ISI_SET_SNDBUF */ char *path; /* Pathname for ServerPath */ int pathlen; /* Length of path */