Hi,

On Mon, Feb 16, 2026 at 12:02:33PM +0100, Anthonin Bonnefoy wrote:
> On Fri, Feb 13, 2026 at 11:08 AM Bertrand Drouvot
> <[email protected]> wrote:
> > It's not as important as when a struct which is used as an hash key has 
> > padding
> > bytes uninitialized (and byte comparisons are done on the key) but I'm also
> > +1 to make it "cleaner".
> 
> Yeah, there's no direct issue of having those uninitialized. The only
> impact I can think of is reducing compression efficiency of the WAL
> due to the random padding bytes.

Yeah, good point about the compression.

> >
> > That's also what I recall, and what we followed in [1].
> 
> I think that depends on the C standard used. With C99, there's no rule
> for the padding bytes initialization.
> With C11, in 6.7.9 Initialization of the standard: "the remainder of
> the aggregate shall be initialized implicitly the same as objects that
> have static storage duration", and with static storage will "every
> member is initialized (recursively) according to these rules, and any
> padding is initialized to zero bits".

Thanks for the research!

> So if I read this correctly, '{0}' will set padding bytes to 0 when
> using C11. But given Postgres is using C99, that's not something we
> can rely on?

C11 is required as of f5e0186f865c so it looks like we could make use of
{0} instead.

> > > True about the initialization part, mostly I guess, still we tend to
> > > worry about eliminating padding because these are wasted bytes in the
> > > WAL records.  For example, xlhp_freeze_plans has two bytes of padding,
> > > that we eliminate while inserting its record by splitting the
> > > FLEXIBLE_ARRAY_MEMBER part.
> >
> > But in the case of this thread it's in the middle of the struct, so I'm not
> > sure the "wasted" bytes would be elminated, would it?
> 
> Moving subxid_overflow before xids, wouldn't you have 3 bytes of
> padding at the end of the struct for the whole struct alignment?

Yeah, we'd go from:

/* offset      |    size */  type = struct xl_running_xacts {
/*      0      |       4 */    int xcnt;
/*      4      |       4 */    int subxcnt;
/*      8      |       1 */    _Bool subxid_overflow;
/* XXX  3-byte hole      */
/*     12      |       4 */    TransactionId nextXid;
/*     16      |       4 */    TransactionId oldestRunningXid;
/*     20      |       4 */    TransactionId latestCompletedXid;
/*     24      |       0 */    TransactionId xids[];

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

to

/* offset      |    size */  type = struct xl_running_xacts {
/*      0      |       4 */    int xcnt;
/*      4      |       4 */    int subxcnt;
/*      8      |       4 */    TransactionId nextXid;
/*     12      |       4 */    TransactionId oldestRunningXid;
/*     16      |       4 */    TransactionId latestCompletedXid;
/*     20      |       1 */    _Bool subxid_overflow;
/* XXX  3-byte hole      */
/*     24      |       0 */    TransactionId xids[];

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

By moving subxid_overflow before the flexible array.

Regards,

-- 
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com


Reply via email to