提交 3ec52323 编写于 作者: T Tom Lane

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...
上级 ad4a574b
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.29 1999/08/31 01:37:36 tgl Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.30 1999/09/13 03:00:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -307,6 +307,7 @@ pqReadReady(PGconn *conn) ...@@ -307,6 +307,7 @@ pqReadReady(PGconn *conn)
int int
pqReadData(PGconn *conn) pqReadData(PGconn *conn)
{ {
int someread = 0;
int nread; int nread;
if (conn->sock < 0) if (conn->sock < 0)
...@@ -359,11 +360,11 @@ tryAgain: ...@@ -359,11 +360,11 @@ tryAgain:
/* Some systems return EAGAIN/EWOULDBLOCK for no data */ /* Some systems return EAGAIN/EWOULDBLOCK for no data */
#ifdef EAGAIN #ifdef EAGAIN
if (errno == EAGAIN) if (errno == EAGAIN)
return 0; return someread;
#endif #endif
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN)) #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
if (errno == EWOULDBLOCK) if (errno == EWOULDBLOCK)
return 0; return someread;
#endif #endif
/* We might get ECONNRESET here if using TCP and backend died */ /* We might get ECONNRESET here if using TCP and backend died */
#ifdef ECONNRESET #ifdef ECONNRESET
...@@ -378,9 +379,30 @@ tryAgain: ...@@ -378,9 +379,30 @@ tryAgain:
if (nread > 0) if (nread > 0)
{ {
conn->inEnd += nread; conn->inEnd += nread;
/*
* Hack to deal with the fact that some kernels will only give us
* back 1 packet per recv() call, even if we asked for more and there
* is more available. If it looks like we are reading a long message,
* loop back to recv() again immediately, until we run out of data
* or buffer space. Without this, the block-and-restart behavior of
* libpq's higher levels leads to O(N^2) performance on long messages.
*
* Since we left-justified the data above, conn->inEnd gives the
* amount of data already read in the current message. We consider
* the message "long" once we have acquired 32k ...
*/
if (conn->inEnd > 32768 &&
(conn->inBufSize - conn->inEnd) >= 8192)
{
someread = 1;
goto tryAgain;
}
return 1; return 1;
} }
if (someread)
return 1; /* got a zero read after successful tries */
/* /*
* A return value of 0 could mean just that no data is now available, * A return value of 0 could mean just that no data is now available,
* or it could mean EOF --- that is, the server has closed the * or it could mean EOF --- that is, the server has closed the
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册