public inbox for [email protected]  
help / color / mirror / Atom feed
From: Heikki Linnakangas <[email protected]>
To: Bertrand Drouvot <[email protected]>
Cc: Andres Freund <[email protected]>
Cc: [email protected] <[email protected]>
Subject: Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)
Date: Wed, 11 Feb 2026 12:03:51 +0200
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>
	<[email protected]>

On 11/02/2026 06:40, Bertrand Drouvot wrote:
> A few comments:
> 
> 0001:
> 
> + * and (b) to make the multiplication / division to convert between PGPROC *
> + * and ProcNumber be a little cheaper
> 
> Is that correct if PGPROC size is not a power of 2?

You're right, it's not.

> 0002: Good catch!

Committed that.

>> With this, sizeof(PGPROC) == 864 without the explicit alignment to
>> PG_CACHE_LINE_SIZE, and 896 with it.
> 
> I can see 876 -> 896 on my side:
> 
> /*    872      |       4 */    uint32 wait_event_info;
> /* XXX 20-byte padding   */
> 
>                                 /* total size (bytes):  896 */
>                               }

Interesting. I've attached 'pahole bin/postgres' output from my laptop. 
It's Linux on arm64. This is with my v2 patches to rearrange the fields, 
but with the "pg_attribute_aligned(PG_CACHE_LINE_SIZE)" removed.

- Heikki

struct PGPROC {
	dlist_head *               procgloballist;       /*     0     8 */
	dlist_node                 freeProcsLink;        /*     8    16 */
	int                        pid;                  /*    24     4 */
	BackendType                backendType;          /*    28     4 */
	Oid                        databaseId;           /*    32     4 */
	Oid                        roleId;               /*    36     4 */
	Oid                        tempNamespaceId;      /*    40     4 */
	int                        pgxactoff;            /*    44     4 */
	uint8                      statusFlags;          /*    48     1 */

	/* XXX 3 bytes hole, try to pack */

	struct {
		ProcNumber         procNumber;           /*    52     4 */
		LocalTransactionId lxid;                 /*    56     4 */
	} vxid;                                          /*    52     8 */
	TransactionId              xid;                  /*    60     4 */
	/* --- cacheline 1 boundary (64 bytes) --- */
	TransactionId              xmin;                 /*    64     4 */
	XidCacheStatus             subxidStatus;         /*    68     2 */

	/* XXX 2 bytes hole, try to pack */

	struct XidCache            subxids;              /*    72   256 */
	/* --- cacheline 5 boundary (320 bytes) was 8 bytes ago --- */
	Latch                      procLatch;            /*   328    16 */
	PGSemaphore                sem;                  /*   344     8 */
	int                        delayChkptFlags;      /*   352     4 */
	pg_atomic_uint32           pendingRecoveryConflicts; /*   356     4 */
	uint8                      lwWaiting;            /*   360     1 */
	uint8                      lwWaitMode;           /*   361     1 */

	/* XXX 2 bytes hole, try to pack */

	proclist_node              lwWaitLink;           /*   364     8 */
	proclist_node              cvWaitLink;           /*   372     8 */

	/* XXX 4 bytes hole, try to pack */

	/* --- cacheline 6 boundary (384 bytes) --- */
	PGPROC *                   lockGroupLeader;      /*   384     8 */
	dlist_head                 lockGroupMembers;     /*   392    16 */
	dlist_node                 lockGroupLink;        /*   408    16 */
	LOCK *                     waitLock;             /*   424     8 */
	dlist_node                 waitLink;             /*   432    16 */
	/* --- cacheline 7 boundary (448 bytes) --- */
	PROCLOCK *                 waitProcLock;         /*   448     8 */
	LOCKMODE                   waitLockMode;         /*   456     4 */
	LOCKMASK                   heldLocks;            /*   460     4 */
	pg_atomic_uint64           waitStart __attribute__((__aligned__(8))); /*   464     8 */
	ProcWaitStatus             waitStatus;           /*   472     4 */

	/* XXX 4 bytes hole, try to pack */

	dlist_head                 myProcLocks[16];      /*   480   256 */
	/* --- cacheline 11 boundary (704 bytes) was 32 bytes ago --- */
	LWLock                     fpInfoLock;           /*   736    16 */
	uint64 *                   fpLockBits;           /*   752     8 */
	Oid *                      fpRelId;              /*   760     8 */
	/* --- cacheline 12 boundary (768 bytes) --- */
	_Bool                      fpVXIDLock;           /*   768     1 */

	/* XXX 3 bytes hole, try to pack */

	LocalTransactionId         fpLocalTransactionId; /*   772     4 */
	XLogRecPtr                 waitLSN;              /*   776     8 */
	int                        syncRepState;         /*   784     4 */

	/* XXX 4 bytes hole, try to pack */

	dlist_node                 syncRepLinks;         /*   792    16 */
	_Bool                      procArrayGroupMember; /*   808     1 */

	/* XXX 3 bytes hole, try to pack */

	pg_atomic_uint32           procArrayGroupNext;   /*   812     4 */
	TransactionId              procArrayGroupMemberXid; /*   816     4 */
	_Bool                      clogGroupMember;      /*   820     1 */

	/* XXX 3 bytes hole, try to pack */

	pg_atomic_uint32           clogGroupNext;        /*   824     4 */
	TransactionId              clogGroupMemberXid;   /*   828     4 */
	/* --- cacheline 13 boundary (832 bytes) --- */
	XidStatus                  clogGroupMemberXidStatus; /*   832     4 */

	/* XXX 4 bytes hole, try to pack */

	int64                      clogGroupMemberPage;  /*   840     8 */
	XLogRecPtr                 clogGroupMemberLsn;   /*   848     8 */
	uint32                     wait_event_info;      /*   856     4 */

	/* size: 864, cachelines: 14, members: 51 */
	/* sum members: 828, holes: 10, sum holes: 32 */
	/* padding: 4 */
	/* forced alignments: 1 */
	/* last cacheline: 32 bytes */
} __attribute__((__aligned__(8)));


Attachments:

  [text/plain] pahole-PGPROC.txt (4.5K, 2-pahole-PGPROC.txt)
  download | inline:
struct PGPROC {
	dlist_head *               procgloballist;       /*     0     8 */
	dlist_node                 freeProcsLink;        /*     8    16 */
	int                        pid;                  /*    24     4 */
	BackendType                backendType;          /*    28     4 */
	Oid                        databaseId;           /*    32     4 */
	Oid                        roleId;               /*    36     4 */
	Oid                        tempNamespaceId;      /*    40     4 */
	int                        pgxactoff;            /*    44     4 */
	uint8                      statusFlags;          /*    48     1 */

	/* XXX 3 bytes hole, try to pack */

	struct {
		ProcNumber         procNumber;           /*    52     4 */
		LocalTransactionId lxid;                 /*    56     4 */
	} vxid;                                          /*    52     8 */
	TransactionId              xid;                  /*    60     4 */
	/* --- cacheline 1 boundary (64 bytes) --- */
	TransactionId              xmin;                 /*    64     4 */
	XidCacheStatus             subxidStatus;         /*    68     2 */

	/* XXX 2 bytes hole, try to pack */

	struct XidCache            subxids;              /*    72   256 */
	/* --- cacheline 5 boundary (320 bytes) was 8 bytes ago --- */
	Latch                      procLatch;            /*   328    16 */
	PGSemaphore                sem;                  /*   344     8 */
	int                        delayChkptFlags;      /*   352     4 */
	pg_atomic_uint32           pendingRecoveryConflicts; /*   356     4 */
	uint8                      lwWaiting;            /*   360     1 */
	uint8                      lwWaitMode;           /*   361     1 */

	/* XXX 2 bytes hole, try to pack */

	proclist_node              lwWaitLink;           /*   364     8 */
	proclist_node              cvWaitLink;           /*   372     8 */

	/* XXX 4 bytes hole, try to pack */

	/* --- cacheline 6 boundary (384 bytes) --- */
	PGPROC *                   lockGroupLeader;      /*   384     8 */
	dlist_head                 lockGroupMembers;     /*   392    16 */
	dlist_node                 lockGroupLink;        /*   408    16 */
	LOCK *                     waitLock;             /*   424     8 */
	dlist_node                 waitLink;             /*   432    16 */
	/* --- cacheline 7 boundary (448 bytes) --- */
	PROCLOCK *                 waitProcLock;         /*   448     8 */
	LOCKMODE                   waitLockMode;         /*   456     4 */
	LOCKMASK                   heldLocks;            /*   460     4 */
	pg_atomic_uint64           waitStart __attribute__((__aligned__(8))); /*   464     8 */
	ProcWaitStatus             waitStatus;           /*   472     4 */

	/* XXX 4 bytes hole, try to pack */

	dlist_head                 myProcLocks[16];      /*   480   256 */
	/* --- cacheline 11 boundary (704 bytes) was 32 bytes ago --- */
	LWLock                     fpInfoLock;           /*   736    16 */
	uint64 *                   fpLockBits;           /*   752     8 */
	Oid *                      fpRelId;              /*   760     8 */
	/* --- cacheline 12 boundary (768 bytes) --- */
	_Bool                      fpVXIDLock;           /*   768     1 */

	/* XXX 3 bytes hole, try to pack */

	LocalTransactionId         fpLocalTransactionId; /*   772     4 */
	XLogRecPtr                 waitLSN;              /*   776     8 */
	int                        syncRepState;         /*   784     4 */

	/* XXX 4 bytes hole, try to pack */

	dlist_node                 syncRepLinks;         /*   792    16 */
	_Bool                      procArrayGroupMember; /*   808     1 */

	/* XXX 3 bytes hole, try to pack */

	pg_atomic_uint32           procArrayGroupNext;   /*   812     4 */
	TransactionId              procArrayGroupMemberXid; /*   816     4 */
	_Bool                      clogGroupMember;      /*   820     1 */

	/* XXX 3 bytes hole, try to pack */

	pg_atomic_uint32           clogGroupNext;        /*   824     4 */
	TransactionId              clogGroupMemberXid;   /*   828     4 */
	/* --- cacheline 13 boundary (832 bytes) --- */
	XidStatus                  clogGroupMemberXidStatus; /*   832     4 */

	/* XXX 4 bytes hole, try to pack */

	int64                      clogGroupMemberPage;  /*   840     8 */
	XLogRecPtr                 clogGroupMemberLsn;   /*   848     8 */
	uint32                     wait_event_info;      /*   856     4 */

	/* size: 864, cachelines: 14, members: 51 */
	/* sum members: 828, holes: 10, sum holes: 32 */
	/* padding: 4 */
	/* forced alignments: 1 */
	/* last cacheline: 32 bytes */
} __attribute__((__aligned__(8)));

view thread (22+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected]
  Subject: Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox