>From 7c8b13a6eeb257d8cadf965b4d46b838fe3a5460 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Fri, 3 Oct 2014 15:48:42 +0300
Subject: [PATCH 2/2] Move the CRC calculations into the other loop through
 XLogRecDatas.

For some reason, this makes a big difference to performance of a simple
test case that does a lot of heap insertions to a narrow table.
---
 src/backend/access/transam/xlog.c       | 20 +-------------------
 src/backend/access/transam/xloginsert.c | 17 ++++++++++++++---
 2 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 5dec637..d1b874d 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -859,7 +859,6 @@ XLogRecPtr
 XLogInsertRecData(XLogRecData *rdata, bool fpw_sensitive)
 {
 	XLogCtlInsert *Insert = &XLogCtl->Insert;
-	XLogRecData *rdt;
 	pg_crc32	rdata_crc;
 	bool		inserted;
 	XLogRecord *rechdr = (XLogRecord *) rdata->data;
@@ -894,24 +893,6 @@ XLogInsertRecData(XLogRecData *rdata, bool fpw_sensitive)
 	if (rechdr->xl_len == 0 && !isLogSwitch)
 		elog(PANIC, "invalid xlog record length %u", rechdr->xl_len);
 
-	/*
-	 * Calculate CRC of the data, including all the backup blocks
-	 *
-	 * Note that the record header isn't added into the CRC initially since we
-	 * don't know the prev-link yet.  Thus, the CRC will represent the CRC of
-	 * the whole record in the order: rdata, then backup blocks, then record
-	 * header.
-	 */
-	INIT_CRC32(rdata_crc);
-	for (rdt = rdata->next; rdt != NULL; rdt = rdt->next)
-		COMP_CRC32(rdata_crc, rdt->data, rdt->len);
-
-	/*
-	 * Calculate CRC of the header, except for prev-link, because we don't
-	 * know it yet.  It will be added later.
-	 */
-	COMP_CRC32(rdata_crc, ((char *) rechdr), offsetof(XLogRecord, xl_prev));
-
 	/*----------
 	 *
 	 * We have now done all the preparatory work we can without holding a
@@ -1014,6 +995,7 @@ XLogInsertRecData(XLogRecData *rdata, bool fpw_sensitive)
 		 * Now that xl_prev has been filled in, finish CRC calculation of the
 		 * record header.
 		 */
+		rdata_crc = rechdr->xl_crc;
 		COMP_CRC32(rdata_crc, ((char *) &rechdr->xl_prev), sizeof(XLogRecPtr));
 		FIN_CRC32(rdata_crc);
 		rechdr->xl_crc = rdata_crc;
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index c5be328..d9a2be09 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -130,6 +130,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecData *rdata,
 	uint32		len,
 				total_len;
 	unsigned	i;
+	pg_crc32	rdata_crc;
 
 	/*
 	 * These need to be static because they are returned to the caller as part
@@ -171,6 +172,8 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecData *rdata,
 		dtbuf_bkp[i] = false;
 	}
 
+	INIT_CRC32(rdata_crc);
+
 	*page_writes_omitted = false;
 	len = 0;
 	for (rdt = rdata;;)
@@ -235,6 +238,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecData *rdata,
 				elog(PANIC, "can backup at most %d blocks per xlog record",
 					 XLR_MAX_BKP_BLOCKS);
 		}
+		COMP_CRC32(rdata_crc, rdt->data, rdt->len);
 		/* Break out of loop when rdt points to last chain item */
 		if (rdt->next == NULL)
 			break;
@@ -274,6 +278,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecData *rdata,
 		rdt->data = (char *) bkpb;
 		rdt->len = sizeof(BkpBlock);
 		total_len += sizeof(BkpBlock);
+		COMP_CRC32(rdata_crc, rdt->data, rdt->len);
 
 		rdt->next = &(dtbuf_rdt2[i]);
 		rdt = rdt->next;
@@ -284,6 +289,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecData *rdata,
 			rdt->len = BLCKSZ;
 			total_len += BLCKSZ;
 			rdt->next = NULL;
+			COMP_CRC32(rdata_crc, rdt->data, rdt->len);
 		}
 		else
 		{
@@ -291,6 +297,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecData *rdata,
 			rdt->data = page;
 			rdt->len = bkpb->hole_offset;
 			total_len += bkpb->hole_offset;
+			COMP_CRC32(rdata_crc, rdt->data, rdt->len);
 
 			rdt->next = &(dtbuf_rdt3[i]);
 			rdt = rdt->next;
@@ -299,13 +306,14 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecData *rdata,
 			rdt->len = BLCKSZ - (bkpb->hole_offset + bkpb->hole_length);
 			total_len += rdt->len;
 			rdt->next = NULL;
+			COMP_CRC32(rdata_crc, rdt->data, rdt->len);
 		}
 	}
 
 	/*
-	 * Fill in the fields in the record header. Prev-link is filled in later,
-	 * once we know where in the WAL the record will be inserted. CRC is also
-	 * not calculated yet.
+	 * Fill in the fields in the record header, except for the prev-link
+	 * because we don't know it yet. It will be filled in and added to the
+	 * CRC later, in XLogInsertRecData.
 	 */
 	rechdr->xl_xid = GetCurrentTransactionIdIfAny();
 	rechdr->xl_tot_len = total_len;
@@ -314,6 +322,9 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecData *rdata,
 	rechdr->xl_rmid = rmid;
 	rechdr->xl_prev = InvalidXLogRecPtr;
 
+	COMP_CRC32(rdata_crc, ((char *) rechdr), offsetof(XLogRecord, xl_prev));
+	rechdr->xl_crc = rdata_crc;
+
 	return &hdr_rdt;
 }
 
-- 
2.1.1

