Обсуждение: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

Поиск
Список
Период
Сортировка

PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Heikki Linnakangas
Дата:
(moving to pgsql-hackers)

On 10/02/2026 18:41, Andres Freund wrote:
> On 2026-02-10 17:52:16 +0200, Heikki Linnakangas wrote:
>> If there's a performance reason to keep have it be aligned - and maybe there
>> is - we should pad it explicitly.
> 
> We should make it a power of two or such. There are some workloads where the
> indexing from GetPGProcByNumber() shows up, because it ends up having to be
> implemented as a 64 bit multiplication, which has a reasonably high latency
> (3-5 cycles). Whereas a shift has a latency of 1 and typically higher
> throughput too.

Power of two means going to 1024 bytes. That's a lot of padding. Where 
have you seen that show up?

Attached is a patch to align to cache line boundary. That's 
straightforward if that's what we want to do.

> Re false sharing: We should really separate stuff that changes (like
> e.g. pendingRecoveryConflicts) and never changing stuff (backendType). You
> don't need overlapping structs to have false sharing issues if you mix
> different access patterns inside a struct that's accessed across processes...

Makes sense, although I don't want to optimize too hard for performance, 
at the expense of readability. The current order is pretty random 
anyway, though.

It'd probably be good to move the subxids cache to the end of the 
struct. That'd act as natural padding, as it's not very frequently used, 
especially the tail end of the cache. Or come to think of it, it might 
be good to move the subxids cache out of PGPROC altogether. It's mostly 
frequently accessed in GetSnapshotData(), and for that it'd actually be 
better if it was in a separate "mirrored" array, similar to the main xid 
and subxidStates. That would eliminate the pgprocnos[pgxactoff] lookup 
from GetSnapshotdata() altogether.

I'm a little reluctant to mess with this without a concrete benchmark 
though. Got one in mind?

- Heikki

Вложения

Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Andres Freund
Дата:
Hi,

On 2026-02-10 19:14:44 +0200, Heikki Linnakangas wrote:
> On 10/02/2026 18:41, Andres Freund wrote:
> > On 2026-02-10 17:52:16 +0200, Heikki Linnakangas wrote:
> > > If there's a performance reason to keep have it be aligned - and maybe there
> > > is - we should pad it explicitly.
> > 
> > We should make it a power of two or such. There are some workloads where the
> > indexing from GetPGProcByNumber() shows up, because it ends up having to be
> > implemented as a 64 bit multiplication, which has a reasonably high latency
> > (3-5 cycles). Whereas a shift has a latency of 1 and typically higher
> > throughput too.
> 
> Power of two means going to 1024 bytes. That's a lot of padding. Where have
> you seen that show up?

LWLock contention heavy code, due to the GetPGProcByNumber() in LWLockWakeup()
and other similar places.


> Attached is a patch to align to cache line boundary. That's straightforward
> if that's what we want to do.

Yea, I think we should do that. Even if we don't see a difference today, just
because it's a hell to find production issues around this, because it is so
dependent on what processes use which PGPROC etc and because false sharing
issues are generally expensive to debug.


> > Re false sharing: We should really separate stuff that changes (like
> > e.g. pendingRecoveryConflicts) and never changing stuff (backendType). You
> > don't need overlapping structs to have false sharing issues if you mix
> > different access patterns inside a struct that's accessed across processes...
> 
> Makes sense, although I don't want to optimize too hard for performance, at
> the expense of readability. The current order is pretty random anyway,
> though.

Yea, I don't think we need to be perfect here. Just a bit less bad. And, as
you say, the current order doesn't make a lot of sense.
Just grouping things like
- pid, pgxactoff, backendType (i.e. barely if ever changing)
- wait_event_info, waitStart (i.e. very frequently changing, but typically
  accessed within one proc)
- sem, lwWaiting, waitLockMode (i.e. stuff that is updated frequently and
  accessed across processes)


> It'd probably be good to move the subxids cache to the end of the struct.
> That'd act as natural padding, as it's not very frequently used, especially
> the tail end of the cache.

Yea, that'd make sense.


> Or come to think of it, it might be good to move the subxids cache out of
> PGPROC altogether. It's mostly frequently accessed in GetSnapshotData(), and
> for that it'd actually be better if it was in a separate "mirrored" array,
> similar to the main xid and subxidStates. That would eliminate the
> pgprocnos[pgxactoff] lookup from GetSnapshotdata() altogether.

I doubt it's worth it - that way we'd need to move a lot larger array around
during [dis]connect. The subxids stuff is a lot larger than the xid,
statusFlags arrays...


> I'm a little reluctant to mess with this without a concrete benchmark
> though. Got one in mind?

I'm travelling this week, but I'll try to recreate the benchmarks I've seen
this on.  Unfortunately you really need a large machine to really see
differences, without that the memory latency between cores is just too low to
realistically see issues.


Greetings,

Andres Freund



Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Bertrand Drouvot
Дата:
Hi,

On Tue, Feb 10, 2026 at 01:15:01PM -0500, Andres Freund wrote:
> Hi,
> 
> On 2026-02-10 19:14:44 +0200, Heikki Linnakangas wrote:
> Yea, I don't think we need to be perfect here. Just a bit less bad. And, as
> you say, the current order doesn't make a lot of sense.
> Just grouping things like
> - pid, pgxactoff, backendType (i.e. barely if ever changing)
> - wait_event_info, waitStart (i.e. very frequently changing, but typically
>   accessed within one proc)
> - sem, lwWaiting, waitLockMode (i.e. stuff that is updated frequently and
>   accessed across processes)

With an ordering like in the attached (to apply on top of Heikki's patch), we're
back to 832 bytes.

But, then the pg_attribute_aligned() added in Heikki's patch makes it 896 bytes...

"
/*    816      |      16 */    dlist_node lockGroupLink;
/* XXX 64-byte padding   */

                               /* total size (bytes):  896 */
                             }
"

What about applying this new ordering and remove the pg_attribute_aligned()? (I
thought the aligned attribute would be smarter than that and not add this 64 padding
bytes).

Regards,

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

Вложения

Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Andres Freund
Дата:
Hi,

On 2026-02-10 19:15:27 +0000, Bertrand Drouvot wrote:
> On Tue, Feb 10, 2026 at 01:15:01PM -0500, Andres Freund wrote:
> > On 2026-02-10 19:14:44 +0200, Heikki Linnakangas wrote:
> > Yea, I don't think we need to be perfect here. Just a bit less bad. And, as
> > you say, the current order doesn't make a lot of sense.
> > Just grouping things like
> > - pid, pgxactoff, backendType (i.e. barely if ever changing)
> > - wait_event_info, waitStart (i.e. very frequently changing, but typically
> >   accessed within one proc)
> > - sem, lwWaiting, waitLockMode (i.e. stuff that is updated frequently and
> >   accessed across processes)
> 
> With an ordering like in the attached (to apply on top of Heikki's patch), we're
> back to 832 bytes.

You'd really need to insert padding between the sections to make it work...


> But, then the pg_attribute_aligned() added in Heikki's patch makes it 896 bytes...
> 
> "
> /*    816      |      16 */    dlist_node lockGroupLink;
> /* XXX 64-byte padding   */
> 
>                                /* total size (bytes):  896 */
>                              }
> "
> 
> What about applying this new ordering and remove the pg_attribute_aligned()?


> (I thought the aligned attribute would be smarter than that and not add this
> 64 padding bytes).

That's just because we have

/*
 * Assumed cache line size.  This doesn't affect correctness, but can be used
 * for low-level optimizations.  This is mostly used to pad various data
 * structures, to ensure that highly-contended fields are on different cache
 * lines.  Too small a value can hurt performance due to false sharing, while
 * the only downside of too large a value is a few bytes of wasted memory.
 * The default is 128, which should be large enough for all supported
 * platforms.
 */
#define PG_CACHE_LINE_SIZE        128


I don't think we need to worry about the number of bytes here very much. This
isn't much compared to all the other overheads a connection slot has (like the
memory for locks).

Greetings,

Andres Freund



Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Heikki Linnakangas
Дата:
On 10/02/2026 21:46, Andres Freund wrote:
> On 2026-02-10 19:15:27 +0000, Bertrand Drouvot wrote:
>> On Tue, Feb 10, 2026 at 01:15:01PM -0500, Andres Freund wrote:
>>> On 2026-02-10 19:14:44 +0200, Heikki Linnakangas wrote:
>>> Yea, I don't think we need to be perfect here. Just a bit less bad. And, as
>>> you say, the current order doesn't make a lot of sense.
>>> Just grouping things like
>>> - pid, pgxactoff, backendType (i.e. barely if ever changing)
>>> - wait_event_info, waitStart (i.e. very frequently changing, but typically
>>>    accessed within one proc)
>>> - sem, lwWaiting, waitLockMode (i.e. stuff that is updated frequently and
>>>    accessed across processes)
>>
>> With an ordering like in the attached (to apply on top of Heikki's patch), we're
>> back to 832 bytes.
> 
> You'd really need to insert padding between the sections to make it work...

Here's my attempt at grouping things more logically. I didn't insert 
padding and also didn't try to avoid alignment padding. I tried to 
optimize for readability rather than size or performance. That said, I 
would assume that grouping things logically like this would also help to 
avoid false sharing. If not, inserting explicit padding seems like a a 
good fix.

I also think we should split 'links' into two fields. For clarity.

With this, sizeof(PGPROC) == 864 without the explicit alignment to 
PG_CACHE_LINE_SIZE, and 896 with it.

- Heikki

Вложения

Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Bertrand Drouvot
Дата:
Hi,

On Tue, Feb 10, 2026 at 10:53:58PM +0200, Heikki Linnakangas wrote:
> On 10/02/2026 21:46, Andres Freund wrote:
> > On 2026-02-10 19:15:27 +0000, Bertrand Drouvot wrote:
> > > On Tue, Feb 10, 2026 at 01:15:01PM -0500, Andres Freund wrote:
> > > > On 2026-02-10 19:14:44 +0200, Heikki Linnakangas wrote:
> > > > Yea, I don't think we need to be perfect here. Just a bit less bad. And, as
> > > > you say, the current order doesn't make a lot of sense.
> > > > Just grouping things like
> > > > - pid, pgxactoff, backendType (i.e. barely if ever changing)
> > > > - wait_event_info, waitStart (i.e. very frequently changing, but typically
> > > >    accessed within one proc)
> > > > - sem, lwWaiting, waitLockMode (i.e. stuff that is updated frequently and
> > > >    accessed across processes)
> > > 
> > > With an ordering like in the attached (to apply on top of Heikki's patch), we're
> > > back to 832 bytes.
> > 
> > You'd really need to insert padding between the sections to make it work...
> 
> Here's my attempt at grouping things more logically.

Thanks!

> I didn't insert padding
> and also didn't try to avoid alignment padding. I tried to optimize for
> readability rather than size or performance.

Yeah, my attempt was to put the size back to 832 bytes but that's probably not
worth it as stated by Andres up-thread.

> That said, I would assume that
> grouping things logically like this would also help to avoid false sharing.
> If not, inserting explicit padding seems like a a good fix.
> 
> I also think we should split 'links' into two fields. For clarity.
>
 
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?

0002: Good catch!

0003:

1/ There is one missing change in PrintLockQueue() ("links" is still used, and
that should be replaced by "waitLink").

2/ change the comment on top of ProcWakeup?

"
/*
 * ProcWakeup -- wake up a process by setting its latch.
 *
 *   Also remove the process from the wait queue and set its links invalid.
"

s/links/waitLink/?

Also, out of curiosity, with 0003 in place PGPROC size goes from 840 to 856.

0004:

The grouping looks Ok to me. Just one nit for the added comments:

+       /*---- Backend identity ----*/
+       /*---- Transactions and snapshots ----*/
+       /*---- Inter-process signaling ----*/
+       /*---- LWLock waiting ----*/
+       /*---- Lock manager data ----*/
+       /*---- Synchronous replication waiting ----*/
+       /*---- Support for group XID clearing. ----*/
+       /*---- Support for group transaction status update. ----*/
+       /*---- Status reporting ----*/

Some have period and some don't.

> 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 */
                             }
Regards,

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



Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Heikki Linnakangas
Дата:
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

Вложения

Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Bertrand Drouvot
Дата:
Hi,

On Wed, Feb 11, 2026 at 12:03:51PM +0200, Heikki Linnakangas wrote:
> On 11/02/2026 06:40, Bertrand Drouvot wrote:
> > > 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.

Thanks!

Got it: I was using "-DCACHEDEBUG -DWAL_DEBUG -DLOCK_DEBUG -DDEBUG_DEADLOCK"
so that with LOCK_DEBUG in place then LWLock size is 32 bytes (vs 16 in your case).

Regards,

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



Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Bertrand Drouvot
Дата:
Hi,

On Wed, Feb 11, 2026 at 12:03:51PM +0200, Heikki Linnakangas wrote:
> 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.

Looking more closely at:

"
/* GCC supports aligned and packed */
#if defined(__GNUC__)
#define pg_attribute_aligned(a) __attribute__((aligned(a)))
#define pg_attribute_packed() __attribute__((packed))
#elif defined(_MSC_VER)
/*
 * MSVC supports aligned.
 *
 * Packing is also possible but only by wrapping the entire struct definition
 * which doesn't fit into our current macro declarations.
 */
#define pg_attribute_aligned(a) __declspec(align(a))
#else
/*
 * NB: aligned and packed are not given default definitions because they
 * affect code functionality; they *must* be implemented by the compiler
 * if they are to be used.
 */
#endif
"

and what the patch adds:

+/*
+ * If compiler understands aligned pragma, use it to align the struct at cache
+ * line boundaries.  This is just for performance, to (a) avoid false sharing
+ * and (b) to make the multiplication / division to convert between PGPROC *
+ * and ProcNumber be a little cheaper.
+ */
+#if defined(pg_attribute_aligned)
+                       pg_attribute_aligned(PG_CACHE_LINE_SIZE)
+#endif
+PGPROC;

It means that PGPROC is "acceptable" without padding (on compiler that does not
understand the aligned attribute).

OTOH, looking at:

"
typedef union WALInsertLockPadded
{
    WALInsertLock l;
    char        pad[PG_CACHE_LINE_SIZE];
} WALInsertLockPadded;
"

It seems to mean that WALInsertLockPadded is unacceptable without padding (since
it's not using pg_attribute_aligned()).

That looks ok to see PGPROC as an "acceptable" one, if not, should we use the
union trick?

Regards,

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



Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Heikki Linnakangas
Дата:
On 11/02/2026 06:40, Bertrand Drouvot wrote:
> On Tue, Feb 10, 2026 at 10:53:58PM +0200, Heikki Linnakangas wrote:
> 0003:
> 
> 1/ There is one missing change in PrintLockQueue() ("links" is still used, and
> that should be replaced by "waitLink").
> 
> 2/ change the comment on top of ProcWakeup?
> 
> "
> /*
>   * ProcWakeup -- wake up a process by setting its latch.
>   *
>   *   Also remove the process from the wait queue and set its links invalid.
> "
> 
> s/links/waitLink/?

Fixed those and pushed this "Split PGPROC 'links' field into two, for 
clarity" patch. Thanks for the review!

- Heikki




Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Heikki Linnakangas
Дата:
On 11/02/2026 06:40, Bertrand Drouvot wrote:
> 0004:
> 
> The grouping looks Ok to me. Just one nit for the added comments:
> 
> +       /*---- Backend identity ----*/
> +       /*---- Transactions and snapshots ----*/
> +       /*---- Inter-process signaling ----*/
> +       /*---- LWLock waiting ----*/
> +       /*---- Lock manager data ----*/
> +       /*---- Synchronous replication waiting ----*/
> +       /*---- Support for group XID clearing. ----*/
> +       /*---- Support for group transaction status update. ----*/
> +       /*---- Status reporting ----*/
> 
> Some have period and some don't.

Fixed that, and changed to different style for the delimiter comments. 
It's a matter of taste, but I think the new style is closer to what we 
use elsewhere.

On 13/02/2026 10:03, Bertrand Drouvot wrote:
> and what the patch adds:
> 
> +/*
> + * If compiler understands aligned pragma, use it to align the struct at cache
> + * line boundaries.  This is just for performance, to (a) avoid false sharing
> + * and (b) to make the multiplication / division to convert between PGPROC *
> + * and ProcNumber be a little cheaper.
> + */
> +#if defined(pg_attribute_aligned)
> +                       pg_attribute_aligned(PG_CACHE_LINE_SIZE)
> +#endif
> +PGPROC;
> 
> It means that PGPROC is "acceptable" without padding (on compiler that does not
> understand the aligned attribute).
> 
> OTOH, looking at:
> 
> "
> typedef union WALInsertLockPadded
> {
>      WALInsertLock l;
>      char        pad[PG_CACHE_LINE_SIZE];
> } WALInsertLockPadded;
> "
> 
> It seems to mean that WALInsertLockPadded is unacceptable without padding (since
> it's not using pg_attribute_aligned()).
> 
> That looks ok to see PGPROC as an "acceptable" one, if not, should we use the
> union trick?

It seems acceptable to just not align it if the compiler doesn't support 
it. This is just a performance optimization, after all.

Attached is new versions the remaining patches. I think these are ready 
to be committed.

I don't have the hardware and test case that would be sensitive enough 
for these changes in memory layout, so I haven't done any performance 
testing of this. I'd guess this no worse than the old layout. Grouping 
fields together which are used together is usually a good strategy. I 
don't feel obliged to do performance testing of this, given that no one 
did that for the old layout either, so if it happened to be really good 
from a performance point of view, it was purely accidental. But if 
anyone has the means and interest to do that, that'd be much appreciated 
of course.

- Heikki

Вложения

Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Bertrand Drouvot
Дата:
Hi,

On Fri, Feb 20, 2026 at 11:03:09PM +0200, Heikki Linnakangas wrote:
> On 11/02/2026 06:40, Bertrand Drouvot wrote:
> > That looks ok to see PGPROC as an "acceptable" one, if not, should we use the
> > union trick?
> 
> It seems acceptable to just not align it if the compiler doesn't support it.
> This is just a performance optimization, after all.

Agreed.

> Attached is new versions the remaining patches. I think these are ready to
> be committed.

Thanks!

One nit, 0001 is adding the typedef:

"
-struct PGPROC
+typedef struct PGPROC
.
.
.
-};
-
-/* NOTE: "typedef struct PGPROC PGPROC" appears in storage/lock.h. */
+       uint32          wait_event_info;        /* proc's wait information */
+} PGPROC;
"

Would that make more sense to add the typedef when we introduce the explicit
alignment in 0002 (like it was done in your previous
v2-0001-Align-PGPROC-to-cache-line-boundary.patch up-thread)?

Regards,

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



Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Heikki Linnakangas
Дата:
On 21/02/2026 11:42, Bertrand Drouvot wrote:
> On Fri, Feb 20, 2026 at 11:03:09PM +0200, Heikki Linnakangas wrote:
>> On 11/02/2026 06:40, Bertrand Drouvot wrote:
>>> That looks ok to see PGPROC as an "acceptable" one, if not, should we use the
>>> union trick?
>>
>> It seems acceptable to just not align it if the compiler doesn't support it.
>> This is just a performance optimization, after all.
> 
> Agreed.
> 
>> Attached is new versions the remaining patches. I think these are ready to
>> be committed.
> 
> Thanks!
> 
> One nit, 0001 is adding the typedef:
> 
> "
> -struct PGPROC
> +typedef struct PGPROC
> .
> .
> .
> -};
> -
> -/* NOTE: "typedef struct PGPROC PGPROC" appears in storage/lock.h. */
> +       uint32          wait_event_info;        /* proc's wait information */
> +} PGPROC;
> "
> 
> Would that make more sense to add the typedef when we introduce the explicit
> alignment in 0002 (like it was done in your previous
> v2-0001-Align-PGPROC-to-cache-line-boundary.patch up-thread)?

Yeah, I had it as part of the other commit in the previous version, but 
decided to make it part of the other one, so that it's more clear what 
the alignment. I don't think it matters much either way though.

Pushed, thanks for the review!

- Heikki




Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Peter Eisentraut
Дата:
On 13.02.26 09:03, Bertrand Drouvot wrote:
> +/*
> + * If compiler understands aligned pragma, use it to align the struct at cache
> + * line boundaries.  This is just for performance, to (a) avoid false sharing
> + * and (b) to make the multiplication / division to convert between PGPROC *
> + * and ProcNumber be a little cheaper.
> + */
> +#if defined(pg_attribute_aligned)
> +                       pg_attribute_aligned(PG_CACHE_LINE_SIZE)
> +#endif
> +PGPROC;

You can/should use C11 standard alignas(), so you don't need to worry 
about whether it's supported or not.




Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Bertrand Drouvot
Дата:
Hi,

On Mon, Feb 23, 2026 at 05:13:29PM +0100, Peter Eisentraut wrote:
> On 13.02.26 09:03, Bertrand Drouvot wrote:
> > +/*
> > + * If compiler understands aligned pragma, use it to align the struct at cache
> > + * line boundaries.  This is just for performance, to (a) avoid false sharing
> > + * and (b) to make the multiplication / division to convert between PGPROC *
> > + * and ProcNumber be a little cheaper.
> > + */
> > +#if defined(pg_attribute_aligned)
> > +                       pg_attribute_aligned(PG_CACHE_LINE_SIZE)
> > +#endif
> > +PGPROC;
> 
> You can/should use C11 standard alignas(), so you don't need to worry about
> whether it's supported or not.

Oh right, I did not notice 300c8f53247 and following like e7075a3405c, d4c0f91f7d5
and 97e04c74bed.

PFA, 0001 doing so for PGPROC and PgAioUringContext. As those are typedef, 
the patch puts alignas within the struct.

For PGPROC at the start of the struct, I think that placing it on the first member
is the right location because it ensures the whole struct is aligned to PG_CACHE_LINE_SIZE
without adding padding before this member. For example if I set it on backendType,
then it adds 100 bytes of padding and the struct is obviously still a multiple of
PG_CACHE_LINE_SIZE but is now 1024 bytes (instead of 896).

For PgAioUringContext at completion_lock (like suggested by Andres in [1]), which
is also the start of the struct.

I checked and the padding for those are exactly the same after the changes.

0002, is also making use of alignas in ItemPointerData, but this one is more
tricky so I'm not sure that's worth it (given the fact that we still need to
keep pg_attribute_aligned() as explained by Peter in [2]).

[1]: https://postgr.es/m/lsgnps74ictxtm5karcobenxtt5rvoylvbvx7ja6r5rjcund7v%40owxqgv7gisns
[2]: https://postgr.es/m/46f05236-d4d4-4b4e-84d4-faa500f14691%40eisentraut.org

Regards,

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

Вложения

Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Peter Eisentraut
Дата:
On 24.02.26 12:28, Bertrand Drouvot wrote:
>> You can/should use C11 standard alignas(), so you don't need to worry about
>> whether it's supported or not.
> 
> Oh right, I did not notice 300c8f53247 and following like e7075a3405c, d4c0f91f7d5
> and 97e04c74bed.
> 
> PFA, 0001 doing so for PGPROC and PgAioUringContext. As those are typedef,
> the patch puts alignas within the struct.
> 
> For PGPROC at the start of the struct, I think that placing it on the first member
> is the right location because it ensures the whole struct is aligned to PG_CACHE_LINE_SIZE
> without adding padding before this member. For example if I set it on backendType,
> then it adds 100 bytes of padding and the struct is obviously still a multiple of
> PG_CACHE_LINE_SIZE but is now 1024 bytes (instead of 896).
> 
> For PgAioUringContext at completion_lock (like suggested by Andres in [1]), which
> is also the start of the struct.
> 
> I checked and the padding for those are exactly the same after the changes.

I have committed the 0001 patch.

> 0002, is also making use of alignas in ItemPointerData, but this one is more
> tricky so I'm not sure that's worth it (given the fact that we still need to
> keep pg_attribute_aligned() as explained by Peter in [2]).

This doesn't seem worth it to me.  Let's skip it.





Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Bertrand Drouvot
Дата:
Hi,

On Mon, Mar 16, 2026 at 11:42:35AM +0100, Peter Eisentraut wrote:
> On 24.02.26 12:28, Bertrand Drouvot wrote:
> > > You can/should use C11 standard alignas(), so you don't need to worry about
> > > whether it's supported or not.
> > 
> > Oh right, I did not notice 300c8f53247 and following like e7075a3405c, d4c0f91f7d5
> > and 97e04c74bed.
> > 
> > PFA, 0001 doing so for PGPROC and PgAioUringContext. As those are typedef,
> > the patch puts alignas within the struct.
> > 
> > For PGPROC at the start of the struct, I think that placing it on the first member
> > is the right location because it ensures the whole struct is aligned to PG_CACHE_LINE_SIZE
> > without adding padding before this member. For example if I set it on backendType,
> > then it adds 100 bytes of padding and the struct is obviously still a multiple of
> > PG_CACHE_LINE_SIZE but is now 1024 bytes (instead of 896).
> > 
> > For PgAioUringContext at completion_lock (like suggested by Andres in [1]), which
> > is also the start of the struct.
> > 
> > I checked and the padding for those are exactly the same after the changes.
> 
> I have committed the 0001 patch.

Thanks! I don't know why but I don't see it in https://git.postgresql.org/gitweb/?p=postgresql.git;a=summary,
or in the github repo though.

> > 0002, is also making use of alignas in ItemPointerData, but this one is more
> > tricky so I'm not sure that's worth it (given the fact that we still need to
> > keep pg_attribute_aligned() as explained by Peter in [2]).
> 
> This doesn't seem worth it to me.  Let's skip it.

Yeah, that makes sense.

Regards,

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



Re: PGPROC alignment (was Re: pgsql: Separate RecoveryConflictReasons from procsignals)

От
Bertrand Drouvot
Дата:
Hi,

On Mon, Mar 16, 2026 at 11:16:51AM +0000, Bertrand Drouvot wrote:
> Hi,
> 
> On Mon, Mar 16, 2026 at 11:42:35AM +0100, Peter Eisentraut wrote:
> > On 24.02.26 12:28, Bertrand Drouvot wrote:
> > > > You can/should use C11 standard alignas(), so you don't need to worry about
> > > > whether it's supported or not.
> > > 
> > > Oh right, I did not notice 300c8f53247 and following like e7075a3405c, d4c0f91f7d5
> > > and 97e04c74bed.
> > > 
> > > PFA, 0001 doing so for PGPROC and PgAioUringContext. As those are typedef,
> > > the patch puts alignas within the struct.
> > > 
> > > For PGPROC at the start of the struct, I think that placing it on the first member
> > > is the right location because it ensures the whole struct is aligned to PG_CACHE_LINE_SIZE
> > > without adding padding before this member. For example if I set it on backendType,
> > > then it adds 100 bytes of padding and the struct is obviously still a multiple of
> > > PG_CACHE_LINE_SIZE but is now 1024 bytes (instead of 896).
> > > 
> > > For PgAioUringContext at completion_lock (like suggested by Andres in [1]), which
> > > is also the start of the struct.
> > > 
> > > I checked and the padding for those are exactly the same after the changes.
> > 
> > I have committed the 0001 patch.
> 
> Thanks! I don't know why but I don't see it in https://git.postgresql.org/gitweb/?p=postgresql.git;a=summary,
> or in the github repo though.

FWIW, I reached out to sysadmins@ and it has now been fixed.

Regards,

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