1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-17 06:41:24 +03:00

Fix performance bug in write_syslog(): the code to preferentially break the

log message at newlines cost O(N^2) for very long messages with few or no
newlines.  For messages in the megabyte range this became the dominant cost.
Per gripe from Achilleas Mantzios.

Patch all the way back, since this is a safe change with no portability
risks.  I am also thinking of increasing PG_SYSLOG_LIMIT, but that should
be done separately.
This commit is contained in:
Tom Lane 2008-07-08 22:18:18 +00:00
parent 99772d6465
commit 20c20dfeec

View File

@ -37,7 +37,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.125.2.3 2007/07/21 22:12:32 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.125.2.4 2008/07/08 22:18:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -925,7 +925,8 @@ write_syslog(int level, const char *line)
static bool openlog_done = false; static bool openlog_done = false;
static unsigned long seq = 0; static unsigned long seq = 0;
int len = strlen(line); int len;
const char *nlpos;
if (Use_syslog == 0) if (Use_syslog == 0)
return; return;
@ -965,8 +966,10 @@ write_syslog(int level, const char *line)
seq++; seq++;
/* divide into multiple syslog() calls if message is too long */ /* divide into multiple syslog() calls if message is too long */
/* or if the message contains embedded NewLine(s) '\n' */ /* or if the message contains embedded newline(s) */
if (len > PG_SYSLOG_LIMIT || strchr(line, '\n') != NULL) len = strlen(line);
nlpos = strchr(line, '\n');
if (len > PG_SYSLOG_LIMIT || nlpos != NULL)
{ {
int chunk_nr = 0; int chunk_nr = 0;
@ -981,15 +984,19 @@ write_syslog(int level, const char *line)
{ {
line++; line++;
len--; len--;
/* we need to recompute the next newline's position, too */
nlpos = strchr(line, '\n');
continue; continue;
} }
strncpy(buf, line, PG_SYSLOG_LIMIT); /* copy one line, or as much as will fit, to buf */
buf[PG_SYSLOG_LIMIT] = '\0'; if (nlpos != NULL)
if (strchr(buf, '\n') != NULL) buflen = nlpos - line;
*strchr(buf, '\n') = '\0'; else
buflen = len;
buflen = strlen(buf); buflen = Min(buflen, PG_SYSLOG_LIMIT);
memcpy(buf, line, buflen);
buf[buflen] = '\0';
/* trim to multibyte letter boundary */ /* trim to multibyte letter boundary */
buflen = pg_mbcliplen(buf, buflen, buflen); buflen = pg_mbcliplen(buf, buflen, buflen);
@ -998,8 +1005,8 @@ write_syslog(int level, const char *line)
buf[buflen] = '\0'; buf[buflen] = '\0';
/* already word boundary? */ /* already word boundary? */
if (!isspace((unsigned char) line[buflen]) && if (line[buflen] != '\0' &&
line[buflen] != '\0') !isspace((unsigned char) line[buflen]))
{ {
/* try to divide at word boundary */ /* try to divide at word boundary */
i = buflen - 1; i = buflen - 1;