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

Reply via email to