Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4d63e26

Browse files
committed
Further hacking on performance of COPY OUT. It seems that fwrite()'s
per-call overhead is quite significant, at least on Linux: whatever it's doing is more than just shoving the bytes into a buffer. Buffering the data so we can call fwrite() just once per row seems to be a win.
1 parent 223ae69 commit 4d63e26

File tree

1 file changed

+40
-45
lines changed

1 file changed

+40
-45
lines changed

src/backend/commands/copy.c

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.265 2006/05/25 18:42:17 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.266 2006/05/26 22:50:02 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -95,7 +95,8 @@ typedef struct CopyStateData
9595
/* low-level state data */
9696
CopyDest copy_dest; /* type of copy source/destination */
9797
FILE *copy_file; /* used if copy_dest == COPY_FILE */
98-
StringInfo fe_msgbuf; /* used if copy_dest == COPY_NEW_FE */
98+
StringInfo fe_msgbuf; /* used for all dests during COPY TO, only
99+
* for dest == COPY_NEW_FE in COPY FROM */
99100
bool fe_copy; /* true for all FE copy dests */
100101
bool fe_eof; /* true if detected end of copy data */
101102
EolType eol_type; /* EOL type of input */
@@ -287,7 +288,6 @@ SendCopyBegin(CopyState cstate)
287288
pq_sendint(&buf, format, 2); /* per-column formats */
288289
pq_endmessage(&buf);
289290
cstate->copy_dest = COPY_NEW_FE;
290-
cstate->fe_msgbuf = makeStringInfo();
291291
}
292292
else if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
293293
{
@@ -364,23 +364,16 @@ SendCopyEnd(CopyState cstate)
364364
{
365365
if (cstate->copy_dest == COPY_NEW_FE)
366366
{
367-
if (cstate->binary)
368-
{
369-
/* Need to flush out file trailer word */
370-
CopySendEndOfRow(cstate);
371-
}
372-
else
373-
{
374-
/* Shouldn't have any unsent data */
375-
Assert(cstate->fe_msgbuf->len == 0);
376-
}
367+
/* Shouldn't have any unsent data */
368+
Assert(cstate->fe_msgbuf->len == 0);
377369
/* Send Copy Done message */
378370
pq_putemptymessage('c');
379371
}
380372
else
381373
{
382-
/* The FE/BE protocol uses \n as newline for all platforms */
383-
CopySendData(cstate, "\\.\n", 3);
374+
CopySendData(cstate, "\\.", 2);
375+
/* Need to flush out the trailer (this also appends a newline) */
376+
CopySendEndOfRow(cstate);
384377
pq_endcopyout(false);
385378
}
386379
}
@@ -390,53 +383,34 @@ SendCopyEnd(CopyState cstate)
390383
* CopySendString does the same for null-terminated strings
391384
* CopySendChar does the same for single characters
392385
* CopySendEndOfRow does the appropriate thing at end of each data row
386+
* (data is not actually flushed except by CopySendEndOfRow)
393387
*
394388
* NB: no data conversion is applied by these functions
395389
*----------
396390
*/
397391
static void
398392
CopySendData(CopyState cstate, void *databuf, int datasize)
399393
{
400-
switch (cstate->copy_dest)
401-
{
402-
case COPY_FILE:
403-
fwrite(databuf, datasize, 1, cstate->copy_file);
404-
if (ferror(cstate->copy_file))
405-
ereport(ERROR,
406-
(errcode_for_file_access(),
407-
errmsg("could not write to COPY file: %m")));
408-
break;
409-
case COPY_OLD_FE:
410-
if (pq_putbytes((char *) databuf, datasize))
411-
{
412-
/* no hope of recovering connection sync, so FATAL */
413-
ereport(FATAL,
414-
(errcode(ERRCODE_CONNECTION_FAILURE),
415-
errmsg("connection lost during COPY to stdout")));
416-
}
417-
break;
418-
case COPY_NEW_FE:
419-
appendBinaryStringInfo(cstate->fe_msgbuf,
420-
(char *) databuf, datasize);
421-
break;
422-
}
394+
appendBinaryStringInfo(cstate->fe_msgbuf, (char *) databuf, datasize);
423395
}
424396

425397
static void
426398
CopySendString(CopyState cstate, const char *str)
427399
{
428-
CopySendData(cstate, (void *) str, strlen(str));
400+
appendBinaryStringInfo(cstate->fe_msgbuf, str, strlen(str));
429401
}
430402

431403
static void
432404
CopySendChar(CopyState cstate, char c)
433405
{
434-
CopySendData(cstate, &c, 1);
406+
appendStringInfoCharMacro(cstate->fe_msgbuf, c);
435407
}
436408

437409
static void
438410
CopySendEndOfRow(CopyState cstate)
439411
{
412+
StringInfo fe_msgbuf = cstate->fe_msgbuf;
413+
440414
switch (cstate->copy_dest)
441415
{
442416
case COPY_FILE:
@@ -449,24 +423,40 @@ CopySendEndOfRow(CopyState cstate)
449423
CopySendString(cstate, "\r\n");
450424
#endif
451425
}
426+
427+
(void) fwrite(fe_msgbuf->data, fe_msgbuf->len,
428+
1, cstate->copy_file);
429+
if (ferror(cstate->copy_file))
430+
ereport(ERROR,
431+
(errcode_for_file_access(),
432+
errmsg("could not write to COPY file: %m")));
452433
break;
453434
case COPY_OLD_FE:
454435
/* The FE/BE protocol uses \n as newline for all platforms */
455436
if (!cstate->binary)
456437
CopySendChar(cstate, '\n');
438+
439+
if (pq_putbytes(fe_msgbuf->data, fe_msgbuf->len))
440+
{
441+
/* no hope of recovering connection sync, so FATAL */
442+
ereport(FATAL,
443+
(errcode(ERRCODE_CONNECTION_FAILURE),
444+
errmsg("connection lost during COPY to stdout")));
445+
}
457446
break;
458447
case COPY_NEW_FE:
459448
/* The FE/BE protocol uses \n as newline for all platforms */
460449
if (!cstate->binary)
461450
CopySendChar(cstate, '\n');
451+
462452
/* Dump the accumulated row as one CopyData message */
463-
(void) pq_putmessage('d', cstate->fe_msgbuf->data,
464-
cstate->fe_msgbuf->len);
465-
/* Reset fe_msgbuf to empty */
466-
cstate->fe_msgbuf->len = 0;
467-
cstate->fe_msgbuf->data[0] = '\0';
453+
(void) pq_putmessage('d', fe_msgbuf->data, fe_msgbuf->len);
468454
break;
469455
}
456+
457+
/* Reset fe_msgbuf to empty */
458+
fe_msgbuf->len = 0;
459+
fe_msgbuf->data[0] = '\0';
470460
}
471461

472462
/*
@@ -1237,6 +1227,9 @@ CopyTo(CopyState cstate)
12371227
attr_count = list_length(cstate->attnumlist);
12381228
null_print_client = cstate->null_print; /* default */
12391229

1230+
/* We use fe_msgbuf as a per-row buffer regardless of copy_dest */
1231+
cstate->fe_msgbuf = makeStringInfo();
1232+
12401233
/* Get info about the columns we need to process. */
12411234
out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
12421235
force_quote = (bool *) palloc(num_phys_attrs * sizeof(bool));
@@ -1423,6 +1416,8 @@ CopyTo(CopyState cstate)
14231416
{
14241417
/* Generate trailer for a binary copy */
14251418
CopySendInt16(cstate, -1);
1419+
/* Need to flush out the trailer */
1420+
CopySendEndOfRow(cstate);
14261421
}
14271422

14281423
MemoryContextDelete(mycontext);

0 commit comments

Comments
 (0)