Re: Improve LWLock tranche name visibility across backends
Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
To: Sami Imseih <samimseih@gmail.com>
Cc: Nathan Bossart <nathandbossart@gmail.com>, Rahila Syed <rahilasyed90@gmail.com>, pgsql-hackers <pgsql-hackers@postgresql.org>
Date: 2025-08-13T13:33:13Z
Lists: pgsql-hackers
Hi,
On Tue, Aug 12, 2025 at 04:16:48PM -0500, Sami Imseih wrote:
> I spoke offline with Bertrand and discussed the synchronization of
> the local memory from shared memory. After that discussion it is clear
> we don't need to track the highest used index in shared memory. Because
> the tranche_id comes from a shared counter, it is not possible that
> the same tranche_id can be used twice, so we will not have overlap.
> That means, when we sync, we just need to know the highest used
> index in the local memory ( since that could be populated during
> postmaster startup and inherited via fork ) and start syncing local
> memory from that point.
Thanks for the updated version!
I think that we can also get rid of max_used_index.
Indeed, I can see that it's updated when SetLocalTrancheName() is called.
But I don't think that's needed as that would be perfectly fine to restart always
from the "initial max_used_index" because that should be rare enough and the number
of entries that we scan is not large. That would mean: entry not found? resync
the entire local cache (starting again from the non updated max_used_index).
So, if we agree that we don't need to update max_used_index in
SetLocalTrancheName(), then during SyncLWLockTrancheNames() we could rely only on
DsaPointerIsValid(pointers[i]).
Indeed, those DSA pointers are only valid for dynamically registered tranches.
For example with max_used_index = 5, what you would find is DsaPointerIsValid(pointers[i])
invalid from 0 to 4 and starts to be valid at [5] (if a tranche has been dynamically
added). 5 is exactly:
"
int next_index = LWLockTrancheNames.max_used_index + 1;
"
So we could do something like:
int i = 0;
while (i < LWLockTrancheNames.shmem->allocated &&
!DsaPointerIsValid(shared_ptrs[i]))
{
i++;
}
Now this "i" acts as the "next_index" in v7 and now we can start iterating
from it and sync until it's invalid again.
That way, we get rid of max_used_index and I think that this part is simpler and
easier to understand.
Thoughts?
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
Commits
-
test_dsa: Avoid leaking LWLock tranches.
- c5c74282f2ea 19 (unreleased) landed
-
Teach DSM registry to ERROR if attaching to an uninitialized entry.
- b26d76f64327 18.2 landed
- ac2800ddc185 17.8 landed
- 1165a933aab1 19 (unreleased) landed
-
Add a test harness for the LWLock tranche code.
- 16607718c010 19 (unreleased) landed
-
Revert recent change to RequestNamedLWLockTranche().
- d814d7fc3d52 19 (unreleased) landed
-
Move dynamically-allocated LWLock tranche names to shared memory.
- 38b602b0289f 19 (unreleased) landed
-
Prepare DSM registry for upcoming changes to LWLock tranche names.
- 5487058b56e0 19 (unreleased) landed
-
Add GetNamedDSA() and GetNamedDSHash().
- fe07100e82b0 19 (unreleased) cited