]> granicus.if.org Git - pgbouncer/commitdiff
New tunable 'sbuf_loopcnt' to limit time spent on one socket.
authorMarko Kreen <markokr@gmail.com>
Wed, 19 Nov 2008 12:06:37 +0000 (12:06 +0000)
committerMarko Kreen <markokr@gmail.com>
Wed, 19 Nov 2008 12:06:37 +0000 (12:06 +0000)
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.

doc/config.txt
include/bouncer.h
src/main.c
src/sbuf.c

index d5adbd5adc9a8b67b644b5b07e3205efcb2d14b2..7eba7e3a2d335aeb6274f802091348d031d21810 100644 (file)
@@ -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
index e398a2649959d789bcd5148d017569ba8d5a118a..c34bc0a3ccf3ca9efaac3da292ce9d68555afe41 100644 (file)
@@ -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;
index 98c6cd9f57c7ee53dacbaa526806be2138c9e7c9..1973837f69be8a34564b08493952d218b4e174ef 100644 (file)
@@ -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},
index 02146ade6b98cd15ad664bb4d460e465ae9623c1..f8dcb61c0953acb8eea3260971edb8e72a27c724 100644 (file)
@@ -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);