Reduce padding in WALOpenSegment and XLogReaderState

From: Japin Li <japinli(at)hotmail(dot)com>
To: pgsql-hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Reduce padding in WALOpenSegment and XLogReaderState
Date: 2026-08-14 05:46:41
Message-ID: SY7PR01MB10921EA8A38358A127CF78771B6DA2@SY7PR01MB10921.ausprd01.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers


Hi, hackers

While reviewing patch [1], I noticed that we can reduce padding in both
WALOpenSegment and XLogReaderState by reordering a few fields.

Current layout:
---------------

(gdb) ptype/o WALOpenSegment
type = struct WALOpenSegment {
/* 0 | 4 */ int ws_file;
/* XXX 4-byte hole */
/* 8 | 8 */ XLogSegNo ws_segno;
/* 16 | 4 */ TimeLineID ws_tli;
/* XXX 4-byte padding */

/* total size (bytes): 24 */
}

(gdb) ptype/o XLogReaderState
type = struct XLogReaderState {
/* 0 | 24 */ XLogReaderRoutine routine;
/* 24 | 8 */ uint64 system_identifier;
/* 32 | 8 */ void *private_data;
/* 40 | 8 */ XLogRecPtr ReadRecPtr;
/* 48 | 8 */ XLogRecPtr EndRecPtr;
/* 56 | 8 */ XLogRecPtr abortedRecPtr;
/* 64 | 8 */ XLogRecPtr missingContrecPtr;
/* 72 | 8 */ XLogRecPtr overwrittenRecPtr;
/* 80 | 8 */ XLogRecPtr DecodeRecPtr;
/* 88 | 8 */ XLogRecPtr NextRecPtr;
/* 96 | 8 */ XLogRecPtr PrevRecPtr;
/* 104 | 8 */ DecodedXLogRecord *record;
/* 112 | 8 */ char *decode_buffer;
/* 120 | 8 */ size_t decode_buffer_size;
/* 128 | 1 */ _Bool free_decode_buffer;
/* XXX 7-byte hole */
/* 136 | 8 */ char *decode_buffer_head;
/* 144 | 8 */ char *decode_buffer_tail;
/* 152 | 8 */ DecodedXLogRecord *decode_queue_head;
/* 160 | 8 */ DecodedXLogRecord *decode_queue_tail;
/* 168 | 8 */ char *readBuf;
/* 176 | 4 */ uint32 readLen;
/* 180 | 1028 */ WALSegmentContext segcxt;
/* 1208 | 24 */ WALOpenSegment seg;
/* 1232 | 4 */ uint32 segoff;
/* XXX 4-byte hole */
/* 1240 | 8 */ XLogRecPtr latestPagePtr;
/* 1248 | 4 */ TimeLineID latestPageTLI;
/* XXX 4-byte hole */
/* 1256 | 8 */ XLogRecPtr currRecPtr;
/* 1264 | 4 */ TimeLineID currTLI;
/* XXX 4-byte hole */
/* 1272 | 8 */ XLogRecPtr currTLIValidUntil;
/* 1280 | 4 */ TimeLineID nextTLI;
/* XXX 4-byte hole */
/* 1288 | 8 */ char *readRecordBuf;
/* 1296 | 4 */ uint32 readRecordBufSize;
/* XXX 4-byte hole */
/* 1304 | 8 */ char *errormsg_buf;
/* 1312 | 1 */ _Bool errormsg_deferred;
/* 1313 | 1 */ _Bool nonblocking;
/* XXX 6-byte padding */

/* total size (bytes): 1320 */
}

The proposed change as follows:
-------------------------------

diff --git a/src/include/access/xlogreader.h b/src/include/access/xlogreader.h
index 4a9a687e879..6a52ed819cf 100644
--- a/src/include/access/xlogreader.h
+++ b/src/include/access/xlogreader.h
@@ -45,8 +45,8 @@
typedef struct WALOpenSegment
{
int ws_file; /* segment file descriptor */
- XLogSegNo ws_segno; /* segment number */
TimeLineID ws_tli; /* timeline ID of the currently open file */
+ XLogSegNo ws_segno; /* segment number */
} WALOpenSegment;

/* WALSegmentContext carries context information about WAL segments to read */
@@ -267,9 +267,9 @@ struct XLogReaderState
uint32 readLen;

/* last read XLOG position for data currently in readBuf */
+ uint32 segoff;
WALSegmentContext segcxt;
WALOpenSegment seg;
- uint32 segoff;

/*
* beginning of prior page read, and its TLI. Doesn't necessarily
@@ -278,10 +278,10 @@ struct XLogReaderState
XLogRecPtr latestPagePtr;
TimeLineID latestPageTLI;

- /* beginning of the WAL record being read. */
- XLogRecPtr currRecPtr;
/* timeline to read it from, 0 if a lookup is required */
TimeLineID currTLI;
+ /* beginning of the WAL record being read. */
+ XLogRecPtr currRecPtr;

/*
* Safe point to read to in currTLI if current TLI is historical
@@ -303,8 +303,8 @@ struct XLogReaderState
* Buffer for current ReadRecord result (expandable), used when a record
* crosses a page boundary.
*/
- char *readRecordBuf;
uint32 readRecordBufSize;
+ char *readRecordBuf;

/* Buffer to hold error message */
char *errormsg_buf;

With this reordering, the sizes shrink as follows:

- WALOpenSegment: 24 → 16 bytes
- XLogReaderState: 1320 → 1296 bytes

New layout:
-----------

(gdb) ptype/o WALOpenSegment
type = struct WALOpenSegment {
/* 0 | 4 */ int ws_file;
/* 4 | 4 */ TimeLineID ws_tli;
/* 8 | 8 */ XLogSegNo ws_segno;

/* total size (bytes): 16 */
}

(gdb) ptype/o XLogReaderState
type = struct XLogReaderState {
/* 0 | 24 */ XLogReaderRoutine routine;
/* 24 | 8 */ uint64 system_identifier;
/* 32 | 8 */ void *private_data;
/* 40 | 8 */ XLogRecPtr ReadRecPtr;
/* 48 | 8 */ XLogRecPtr EndRecPtr;
/* 56 | 8 */ XLogRecPtr abortedRecPtr;
/* 64 | 8 */ XLogRecPtr missingContrecPtr;
/* 72 | 8 */ XLogRecPtr overwrittenRecPtr;
/* 80 | 8 */ XLogRecPtr DecodeRecPtr;
/* 88 | 8 */ XLogRecPtr NextRecPtr;
/* 96 | 8 */ XLogRecPtr PrevRecPtr;
/* 104 | 8 */ DecodedXLogRecord *record;
/* 112 | 8 */ char *decode_buffer;
/* 120 | 8 */ size_t decode_buffer_size;
/* 128 | 1 */ _Bool free_decode_buffer;
/* XXX 7-byte hole */
/* 136 | 8 */ char *decode_buffer_head;
/* 144 | 8 */ char *decode_buffer_tail;
/* 152 | 8 */ DecodedXLogRecord *decode_queue_head;
/* 160 | 8 */ DecodedXLogRecord *decode_queue_tail;
/* 168 | 8 */ char *readBuf;
/* 176 | 4 */ uint32 readLen;
/* 180 | 4 */ uint32 segoff;
/* 184 | 1028 */ WALSegmentContext segcxt;
/* XXX 4-byte hole */
/* 1216 | 16 */ WALOpenSegment seg;
/* 1232 | 8 */ XLogRecPtr latestPagePtr;
/* 1240 | 4 */ TimeLineID latestPageTLI;
/* 1244 | 4 */ TimeLineID currTLI;
/* 1248 | 8 */ XLogRecPtr currRecPtr;
/* 1256 | 8 */ XLogRecPtr currTLIValidUntil;
/* 1264 | 4 */ TimeLineID nextTLI;
/* 1268 | 4 */ uint32 readRecordBufSize;
/* 1272 | 8 */ char *readRecordBuf;
/* 1280 | 8 */ char *errormsg_buf;
/* 1288 | 1 */ _Bool errormsg_deferred;
/* 1289 | 1 */ _Bool nonblocking;
/* XXX 6-byte padding */

/* total size (bytes): 1296 */
}

Any thoughts?

[1] https://postgr.es/m/A2BB6471-C150-423C-B6F5-BFEC46BE544B@yandex-team.ru
--
Regards,
Japin Li
ChengDu WenWu Information Technology Co., Ltd.

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Bertrand Drouvot 2026-08-14 05:47:06 Re: pg_control_checkpoint(): add "data_checksum_version" (Pg19)?
Previous Message Japin Li 2026-08-14 05:32:24 Re: Compression of bigger WAL records