From: Marko Kreen Date: Wed, 19 Nov 2008 12:06:37 +0000 (+0000) Subject: New tunable 'sbuf_loopcnt' to limit time spent on one socket. X-Git-Tag: pgbouncer_1_3_rc1~42 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ac4ab0fc88a17fff8cad6f07da9ff12b1f025276;p=pgbouncer New tunable 'sbuf_loopcnt' to limit time spent on one socket. In some situations - eg SMP server, local Postgres and fast network - pgbouncer can run recv()->send() loop many times without blocking on either side. But that means other connections will stall for a long time. To make processing more fair, limit the times of doing recv()->send() one socket. If count reaches limit, just proceed processing other sockets. The processing for that socket will resume on next event loop. Thanks to Alexander Schöcke for report and testing. --- diff --git a/doc/config.txt b/doc/config.txt index d5adbd5..7eba7e3 100644 --- a/doc/config.txt +++ b/doc/config.txt @@ -303,6 +303,15 @@ large. Default: 2048 +==== sbuf_loopcnt ==== + +How many times to process data on one connection, before proceeding. +Without limit, one connection with big resultset can stall pgbouncer +for a long time. One loop processes one `pkt_buf` amount of data. +0 means no limit. + +Default: 5 + ==== tcp_defer_accept ==== Details about following options shouldbe looked from man 7 tcp diff --git a/include/bouncer.h b/include/bouncer.h index e398a26..c34bc0a 100644 --- a/include/bouncer.h +++ b/include/bouncer.h @@ -336,6 +336,7 @@ extern int cf_pause_mode; extern int cf_shutdown; extern int cf_reboot; +extern int cf_sbuf_loopcnt; extern int cf_sbuf_len; extern int cf_tcp_keepalive; extern int cf_tcp_keepcnt; diff --git a/src/main.c b/src/main.c index 98c6cd9..1973837 100644 --- a/src/main.c +++ b/src/main.c @@ -72,6 +72,7 @@ int cf_pool_mode = POOL_SESSION; /* sbuf config */ int cf_sbuf_len = 2048; +int cf_sbuf_loopcnt = 5; int cf_tcp_socket_buffer = 0; #if defined(TCP_DEFER_ACCEPT) || defined(SO_ACCEPTFILTER) int cf_tcp_defer_accept = 1; @@ -154,6 +155,7 @@ ConfElem bouncer_params[] = { {"ignore_startup_parameters", true, CF_STR, &cf_ignore_startup_params}, {"pkt_buf", false, CF_INT, &cf_sbuf_len}, +{"sbuf_loopcnt", true, CF_INT, &cf_sbuf_loopcnt}, {"tcp_defer_accept", true, {cf_get_int, set_defer_accept}, &cf_tcp_defer_accept}, {"tcp_socket_buffer", true, CF_INT, &cf_tcp_socket_buffer}, {"tcp_keepalive", true, CF_INT, &cf_tcp_keepalive}, diff --git a/src/sbuf.c b/src/sbuf.c index 02146ad..f8dcb61 100644 --- a/src/sbuf.c +++ b/src/sbuf.c @@ -585,6 +585,7 @@ static bool allocate_iobuf(SBuf *sbuf) static void sbuf_main_loop(SBuf *sbuf, bool skip_recv) { unsigned free, ok; + int loopcnt = 0; /* sbuf was closed before in this event loop */ if (!sbuf->sock) @@ -602,6 +603,13 @@ static void sbuf_main_loop(SBuf *sbuf, bool skip_recv) goto skip_recv; try_more: + /* avoid spending too much time on single socket */ + if (cf_sbuf_loopcnt > 0 && loopcnt >= cf_sbuf_loopcnt) { + log_debug("loopcnt full"); + return; + } + loopcnt++; + /* make room in buffer */ sbuf_try_resync(sbuf, false);