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

Reply via email to