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)));