Skip to content

Commit 3ec5232

Browse files
committed
Patch to cure O(N^2) behavior in libpq when reading a long
message under a kernel that only returns one packet per recv() call. This didn't use to matter much, but it starts to get annoying with multi-megabyte EXPLAIN VERBOSE responses...
1 parent ad4a574 commit 3ec5232

File tree

1 file changed

+25
-3
lines changed

1 file changed

+25
-3
lines changed

src/interfaces/libpq/fe-misc.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*
2525
*
2626
* IDENTIFICATION
27-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.29 1999/08/31 01:37:36 tgl Exp $
27+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.30 1999/09/13 03:00:19 tgl Exp $
2828
*
2929
*-------------------------------------------------------------------------
3030
*/
@@ -307,6 +307,7 @@ pqReadReady(PGconn *conn)
307307
int
308308
pqReadData(PGconn *conn)
309309
{
310+
int someread = 0;
310311
int nread;
311312

312313
if (conn->sock < 0)
@@ -359,11 +360,11 @@ pqReadData(PGconn *conn)
359360
/* Some systems return EAGAIN/EWOULDBLOCK for no data */
360361
#ifdef EAGAIN
361362
if (errno == EAGAIN)
362-
return 0;
363+
return someread;
363364
#endif
364365
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
365366
if (errno == EWOULDBLOCK)
366-
return 0;
367+
return someread;
367368
#endif
368369
/* We might get ECONNRESET here if using TCP and backend died */
369370
#ifdef ECONNRESET
@@ -378,9 +379,30 @@ pqReadData(PGconn *conn)
378379
if (nread > 0)
379380
{
380381
conn->inEnd += nread;
382+
/*
383+
* Hack to deal with the fact that some kernels will only give us
384+
* back 1 packet per recv() call, even if we asked for more and there
385+
* is more available. If it looks like we are reading a long message,
386+
* loop back to recv() again immediately, until we run out of data
387+
* or buffer space. Without this, the block-and-restart behavior of
388+
* libpq's higher levels leads to O(N^2) performance on long messages.
389+
*
390+
* Since we left-justified the data above, conn->inEnd gives the
391+
* amount of data already read in the current message. We consider
392+
* the message "long" once we have acquired 32k ...
393+
*/
394+
if (conn->inEnd > 32768 &&
395+
(conn->inBufSize - conn->inEnd) >= 8192)
396+
{
397+
someread = 1;
398+
goto tryAgain;
399+
}
381400
return 1;
382401
}
383402

403+
if (someread)
404+
return 1; /* got a zero read after successful tries */
405+
384406
/*
385407
* A return value of 0 could mean just that no data is now available,
386408
* or it could mean EOF --- that is, the server has closed the

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy