Hi, I've identified some opportunities to optimize FastPathTransferRelationLocks(), which transfers locks with a specific lock tag from per-backend fast-path arrays to the shared hash table. The attached patch includes these enhancements.
Currently, FastPathTransferRelationLocks() recalculates the fast-path group on each loop iteration, even though it stays the same. This patch updates the function to calculate the group once and reuse it, improving efficiency. The patch also extends the function's logic to skip not only backends from a different database but also backends with pid=0 (which don’t hold fast-path locks) and groups with no registered fast-path locks. Since MyProc->pid is reset to 0 when a backend exits but MyProc->databaseId remains set, checking only databaseId isn’t enough. Backends with pid=0 also should be skipped. Regards, -- Fujii Masao Advanced Computing Technology Center Research and Development Headquarters NTT DATA CORPORATION
From f0986e753d5e25fe9d9a941be621e0e0e43d47ae Mon Sep 17 00:00:00 2001 From: Fujii Masao <fu...@postgresql.org> Date: Tue, 12 Nov 2024 09:29:52 +0900 Subject: [PATCH v1] Optimize lock transfer from per-backend fast-path arrays to shared hash table. This commit improves FastPathTransferRelationLocks() for transferring locks with a specific lock tag from per-backend fast-path arrays to the shared hash table. Previously, the fast-path group was recalculated on each loop iteration, though it remains the same. This update now calculates the group once and reuses it, improving efficiency. Additionally, the function now skips backends with pid=0 (as they hold no fast-path locks) and skips empty fast-path groups, further enhancing performance. --- src/backend/storage/lmgr/lock.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index edc5020c6a..69c4d156fe 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -2773,6 +2773,10 @@ FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag LWLock *partitionLock = LockHashPartitionLock(hashcode); Oid relid = locktag->locktag_field2; uint32 i; + uint32 group; + + /* fast-path group the lock belongs to */ + group = FAST_PATH_REL_GROUP(relid); /* * Every PGPROC that can potentially hold a fast-path lock is present in @@ -2783,8 +2787,7 @@ FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag for (i = 0; i < ProcGlobal->allProcCount; i++) { PGPROC *proc = &ProcGlobal->allProcs[i]; - uint32 j, - group; + uint32 j; LWLockAcquire(&proc->fpInfoLock, LW_EXCLUSIVE); @@ -2802,16 +2805,17 @@ FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag * less clear that our backend is certain to have performed a memory * fencing operation since the other backend set proc->databaseId. So * for now, we test it after acquiring the LWLock just to be safe. + * + * Also skip backends with pid=0 as they don’t hold fast-path locks, + * and skip groups without any registered fast-path locks. */ - if (proc->databaseId != locktag->locktag_field1) + if (proc->databaseId != locktag->locktag_field1 || proc->pid == 0 || + proc->fpLockBits[group] == 0) { LWLockRelease(&proc->fpInfoLock); continue; } - /* fast-path group the lock belongs to */ - group = FAST_PATH_REL_GROUP(relid); - for (j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++) { uint32 lockmode; -- 2.47.0