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