current jcc.c, 1.457, 1.458 loadcfg.c, 1.159, 1.160 project.h, 1.220, 1.221
Fabian Keil <[email protected]> Mon, 29 May 2017 10:02:13 +0000
| Newsgroups | gmane.comp.web.privoxy.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ijbswa/current
In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv28233
Modified Files:
jcc.c loadcfg.c project.h
Log Message:
Add a receive-buffer-size directive
... which can be used to set the size of the previously statically
allocated buffer in handle_established_connection().
Increasing the buffer size increases Privoxy's memory usage but
can lower the number of context switches and thereby reduce the
cpu usage and potentially increase the throughput.
This is mostly relevant for fast network connections and
large downloads that don't require filtering.
Currently BUFFER_SIZE is kept as default and lower limit
but the default should be increased after some more testing.
A dtrace command like:
sudo dtrace -n 'syscall::read:return /execname == "privoxy"/ { @[execname] = llquantize(arg0, 10, 0, 5, 20); @m = max(arg0)}'
can be used to properly tune the receive-buffer-size.
If the buffer is too large it will increase Privoxy's memory
footprint without any benefit. As the memory is (currently)
cleared before using it, a buffer that is too large can
actually reduce the throughput.
Things could be improved further by upwards scaling the buffer
dynamically based on how much of the previous allocation
was actually used.
Additionally the buffer should be referenced through csp and
also be used for other receive-related functions.
Measured throughput when using four connections to
constantly request a 10 MB file:
~320 MB/s with the default
~400 MB/s with "receive-buffer-size 8192"
~490 MB/s with "receive-buffer-size 16384"
~610 MB/s with "receive-buffer-size 32768"
~700 MB/s with "receive-buffer-size 65536"
~755 MB/s with "receive-buffer-size 131072"
~795 MB/s with "receive-buffer-size 262144"
~804 MB/s with "receive-buffer-size 524288"
~798 MB/s with "receive-buffer-size 1048576"
~780 MB/s with "receive-buffer-size 2097152"
Sponsored by: Robert Klemme
Index: project.h
===================================================================
RCS file: /cvsroot/ijbswa/current/project.h,v
retrieving revision 1.220
retrieving revision 1.221
diff -C2 -d -r1.220 -r1.221
*** project.h 20 Feb 2017 13:44:32 -0000 1.220
--- project.h 29 May 2017 10:02:11 -0000 1.221
***************
*** 1349,1352 ****
--- 1349,1355 ----
size_t buffer_limit;
+ /** Size of the receive buffer */
+ size_t receive_buffer_size;
+
#ifdef FEATURE_TRUST
Index: jcc.c
===================================================================
RCS file: /cvsroot/ijbswa/current/jcc.c,v
retrieving revision 1.457
retrieving revision 1.458
diff -C2 -d -r1.457 -r1.458
*** jcc.c 25 May 2017 11:17:21 -0000 1.457
--- jcc.c 29 May 2017 10:02:11 -0000 1.458
***************
*** 1963,1967 ****
const struct forward_spec *fwd)
{
! char buf[BUFFER_SIZE];
char *hdr;
char *p;
--- 1963,1967 ----
const struct forward_spec *fwd)
{
! char *receive_buffer;
char *hdr;
char *p;
***************
*** 1986,1991 ****
int watch_client_socket;
#endif
! memset(buf, 0, sizeof(buf));
http = csp->http;
--- 1986,2000 ----
int watch_client_socket;
#endif
+ const size_t receive_buffer_size = csp->config->receive_buffer_size;
! receive_buffer = zalloc(receive_buffer_size + 1);
! if (receive_buffer == NULL)
! {
! log_error(LOG_LEVEL_ERROR,
! "Out of memory. Failed to allocate the receive buffer.");
! rsp = cgi_error_memory();
! send_crunch_response(csp, rsp);
! return;
! }
http = csp->http;
***************
*** 2111,2114 ****
--- 2120,2124 ----
}
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2121,2124 ****
--- 2131,2135 ----
#endif
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2147,2151 ****
#endif /* def HAVE_POLL*/
{
! int max_bytes_to_read = sizeof(buf) - 1;
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
--- 2158,2162 ----
#endif /* def HAVE_POLL*/
{
! int max_bytes_to_read = (int)receive_buffer_size;
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
***************
*** 2181,2185 ****
if (csp->expected_client_content_length != 0)
{
! if (csp->expected_client_content_length < (sizeof(buf) - 1))
{
max_bytes_to_read = (int)csp->expected_client_content_length;
--- 2192,2196 ----
if (csp->expected_client_content_length != 0)
{
! if (csp->expected_client_content_length < receive_buffer_size)
{
max_bytes_to_read = (int)csp->expected_client_content_length;
***************
*** 2189,2196 ****
max_bytes_to_read);
}
! assert(max_bytes_to_read < sizeof(buf));
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
! len = read_socket(csp->cfd, buf, max_bytes_to_read);
if (len <= 0)
--- 2200,2207 ----
max_bytes_to_read);
}
! assert(max_bytes_to_read <= receive_buffer_size);
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
! len = read_socket(csp->cfd, receive_buffer, max_bytes_to_read);
if (len <= 0)
***************
*** 2219,2226 ****
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
! if (write_socket(csp->server_connection.sfd, buf, (size_t)len))
{
log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
mark_server_socket_tainted(csp);
return;
}
--- 2230,2238 ----
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
! if (write_socket(csp->server_connection.sfd, receive_buffer, (size_t)len))
{
log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2256,2259 ****
--- 2268,2272 ----
"The server still wants to talk, but the client hung up on us.");
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
#endif /* def _WIN32 */
***************
*** 2261,2265 ****
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
! len = read_socket(csp->server_connection.sfd, buf, sizeof(buf) - 1);
if (len < 0)
--- 2274,2278 ----
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
! len = read_socket(csp->server_connection.sfd, receive_buffer, (int)receive_buffer_size);
if (len < 0)
***************
*** 2276,2279 ****
--- 2289,2293 ----
log_error(LOG_LEVEL_ERROR,
"CONNECT already confirmed. Unable to tell the client about the problem.");
+ freez(receive_buffer);
return;
}
***************
*** 2290,2293 ****
--- 2304,2308 ----
"Unable to tell the client about the problem.");
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2302,2306 ****
if (csp->flags & CSP_FLAG_CHUNKED)
{
! if ((len >= 5) && !memcmp(buf+len-5, "0\r\n\r\n", 5))
{
/* XXX: this is a temporary hack */
--- 2317,2321 ----
if (csp->flags & CSP_FLAG_CHUNKED)
{
! if ((len >= 5) && !memcmp(receive_buffer+len-5, "0\r\n\r\n", 5))
{
/* XXX: this is a temporary hack */
***************
*** 2316,2323 ****
/*
* Add a trailing zero to let be able to use string operations.
* XXX: do we still need this with filter_popups gone?
*/
! buf[len] = '\0';
/*
--- 2331,2350 ----
/*
+ * This is guaranteed by allocating with zalloc_or_die()
+ * and never (intentionally) writing to the last byte.
+ *
+ * receive_buffer_size is the size of the part of the
+ * buffer we intentionally write to, but we actually
+ * allocated receive_buffer_size+1 bytes so the assertion
+ * stays within the allocated range.
+ */
+ assert(receive_buffer[receive_buffer_size] == '\0');
+
+ /*
* Add a trailing zero to let be able to use string operations.
* XXX: do we still need this with filter_popups gone?
*/
! assert(len <= receive_buffer_size);
! receive_buffer[len] = '\0';
/*
***************
*** 2398,2401 ****
--- 2425,2429 ----
freez(p);
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2412,2417 ****
* Let's pretend the server just sent us a blank line.
*/
! snprintf(buf, sizeof(buf), "\r\n");
! len = (int)strlen(buf);
/*
--- 2440,2445 ----
* Let's pretend the server just sent us a blank line.
*/
! snprintf(receive_buffer, receive_buffer_size, "\r\n");
! len = (int)strlen(receive_buffer);
/*
***************
*** 2437,2441 ****
* header, flush the iob and buf, and get out of the way.
*/
! if (add_to_iob(csp->iob, csp->config->buffer_limit, buf, len))
{
size_t hdrlen;
--- 2465,2469 ----
* header, flush the iob and buf, and get out of the way.
*/
! if (add_to_iob(csp->iob, csp->config->buffer_limit, receive_buffer, len))
{
size_t hdrlen;
***************
*** 2456,2459 ****
--- 2484,2488 ----
send_crunch_response(csp, rsp);
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2462,2466 ****
if (write_socket(csp->cfd, hdr, hdrlen)
|| ((flushed = flush_socket(csp->cfd, csp->iob)) < 0)
! || (write_socket(csp->cfd, buf, (size_t)len)))
{
log_error(LOG_LEVEL_CONNECT,
--- 2491,2495 ----
if (write_socket(csp->cfd, hdr, hdrlen)
|| ((flushed = flush_socket(csp->cfd, csp->iob)) < 0)
! || (write_socket(csp->cfd, receive_buffer, (size_t)len)))
{
log_error(LOG_LEVEL_CONNECT,
***************
*** 2468,2471 ****
--- 2497,2501 ----
freez(hdr);
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2484,2491 ****
else
{
! if (write_socket(csp->cfd, buf, (size_t)len))
{
log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
mark_server_socket_tainted(csp);
return;
}
--- 2514,2522 ----
else
{
! if (write_socket(csp->cfd, receive_buffer, (size_t)len))
{
log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2501,2505 ****
* little we can do but send our static out-of-memory page.
*/
! if (add_to_iob(csp->iob, csp->config->buffer_limit, buf, len))
{
log_error(LOG_LEVEL_ERROR, "Out of memory while looking for end of server headers.");
--- 2532,2536 ----
* little we can do but send our static out-of-memory page.
*/
! if (add_to_iob(csp->iob, csp->config->buffer_limit, receive_buffer, len))
{
log_error(LOG_LEVEL_ERROR, "Out of memory while looking for end of server headers.");
***************
*** 2507,2510 ****
--- 2538,2542 ----
send_crunch_response(csp, rsp);
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2527,2530 ****
--- 2559,2563 ----
strlen(INVALID_SERVER_HEADERS_RESPONSE));
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2572,2575 ****
--- 2605,2609 ----
free_http_request(http);
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2612,2615 ****
--- 2646,2650 ----
free_http_request(http);
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2646,2649 ****
--- 2681,2685 ----
freez(hdr);
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2676,2679 ****
--- 2712,2716 ----
freez(hdr);
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2700,2703 ****
--- 2737,2741 ----
strlen(INVALID_SERVER_HEADERS_RESPONSE));
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return;
}
***************
*** 2706,2711 ****
--- 2744,2751 ----
}
mark_server_socket_tainted(csp);
+ freez(receive_buffer);
return; /* huh? we should never get here */
}
+ freez(receive_buffer);
if (csp->content_length == 0)
Index: loadcfg.c
===================================================================
RCS file: /cvsroot/ijbswa/current/loadcfg.c,v
retrieving revision 1.159
retrieving revision 1.160
diff -C2 -d -r1.159 -r1.160
*** loadcfg.c 25 May 2017 11:17:38 -0000 1.159
--- loadcfg.c 29 May 2017 10:02:11 -0000 1.160
***************
*** 159,162 ****
--- 159,163 ----
#define hash_permit_access 3587953268U /* "permit-access" */
#define hash_proxy_info_url 3903079059U /* "proxy-info-url" */
+ #define hash_receive_buffer_size 2880297454U /* "receive-buffer-size */
#define hash_single_threaded 4250084780U /* "single-threaded" */
#define hash_socket_timeout 1809001761U /* "socket-timeout" */
***************
*** 598,601 ****
--- 599,603 ----
config->multi_threaded = 1;
config->buffer_limit = 4096 * 1024;
+ config->receive_buffer_size = BUFFER_SIZE;
config->usermanual = strdup_or_die(USER_MANUAL_URL);
config->proxy_args = strdup_or_die("");
***************
*** 1501,1504 ****
--- 1503,1521 ----
break;
+
+ /* *************************************************************************
+ * receive-buffer-size n
+ * *************************************************************************/
+ case hash_receive_buffer_size :
+ config->receive_buffer_size = (size_t)parse_numeric_value(cmd, arg);
+ if (config->receive_buffer_size < BUFFER_SIZE)
+ {
+ log_error(LOG_LEVEL_INFO,
+ "receive-buffer-size %d seems low and may cause problems."
+ "Consider setting it to at least %d.",
+ config->receive_buffer_size, BUFFER_SIZE);
+ }
+ break;
+
/* *************************************************************************
* single-threaded 0|1
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot