]> granicus.if.org Git - postgresql/commitdiff
Remove unnecessary memcpy when reading WAL record fitting on page
authorMichael Paquier <michael@paquier.xyz>
Mon, 19 Nov 2018 01:25:48 +0000 (10:25 +0900)
committerMichael Paquier <michael@paquier.xyz>
Mon, 19 Nov 2018 01:25:48 +0000 (10:25 +0900)
When reading a WAL record, its contents are copied into an intermediate
buffer.  However, doing so is not necessary if the record fits fully
into the current page, saving one memcpy for each such record.  The
allocation handling of the intermediate buffer is also now done only
when a record crosses a page boundary, shaving some extra cycles when
reading a WAL record.

Author: Andrey Lepikhov
Reviewed-by: Kyotaro Horiguchi, Heikki Linnakangas
Discussion: https://postgr.es/m/c2ea54dd-a1d3-80eb-ddbf-7e6f258e615e@postgrespro.ru

src/backend/access/transam/xlog.c
src/backend/access/transam/xlogreader.c

index 7eed5866d2e5a87dc93a192dfb9242078cfa0e3b..2875fe023aff9da68ddd451f2fa5def2a8fb131e 100644 (file)
@@ -4203,9 +4203,6 @@ CleanupBackupHistory(void)
  * If no valid record is available, returns NULL, or fails if emode is PANIC.
  * (emode must be either PANIC, LOG). In standby mode, retries until a valid
  * record is available.
- *
- * The record is copied into readRecordBuf, so that on successful return,
- * the returned record pointer always points there.
  */
 static XLogRecord *
 ReadRecord(XLogReaderState *xlogreader, XLogRecPtr RecPtr, int emode,
index 0768ca782263599f4d6dde6fb835d3922f0b6053..c5e019bf7757b3e205c8dd4732fcf804b058633e 100644 (file)
@@ -353,19 +353,6 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
                gotheader = false;
        }
 
-       /*
-        * Enlarge readRecordBuf as needed.
-        */
-       if (total_len > state->readRecordBufSize &&
-               !allocate_recordbuf(state, total_len))
-       {
-               /* We treat this as a "bogus data" condition */
-               report_invalid_record(state, "record length %u at %X/%X too long",
-                                                         total_len,
-                                                         (uint32) (RecPtr >> 32), (uint32) RecPtr);
-               goto err;
-       }
-
        len = XLOG_BLCKSZ - RecPtr % XLOG_BLCKSZ;
        if (total_len > len)
        {
@@ -375,6 +362,19 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
                char       *buffer;
                uint32          gotlen;
 
+               /*
+                * Enlarge readRecordBuf as needed.
+                */
+               if (total_len > state->readRecordBufSize &&
+                       !allocate_recordbuf(state, total_len))
+               {
+                       /* We treat this as a "bogus data" condition */
+                       report_invalid_record(state, "record length %u at %X/%X too long",
+                                                                 total_len,
+                                                                 (uint32) (RecPtr >> 32), (uint32) RecPtr);
+                       goto err;
+               }
+
                /* Copy the first fragment of the record from the first page. */
                memcpy(state->readRecordBuf,
                           state->readBuf + RecPtr % XLOG_BLCKSZ, len);
@@ -479,7 +479,6 @@ XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
                state->EndRecPtr = RecPtr + MAXALIGN(total_len);
 
                state->ReadRecPtr = RecPtr;
-               memcpy(state->readRecordBuf, record, total_len);
        }
 
        /*