Refactor GetLockStatusData() to skip backends/groups without fast-path locks.
authorFujii Masao <[email protected]>
Thu, 24 Oct 2024 15:18:32 +0000 (00:18 +0900)
committerFujii Masao <[email protected]>
Thu, 24 Oct 2024 15:18:32 +0000 (00:18 +0900)
Previously, GetLockStatusData() checked all slots for every backend
to gather fast-path lock data, which could be inefficient. This commit
refactors it by skipping backends with PID=0 (since they don't hold
fast-path locks) and skipping groups with no registered fast-path locks,
improving efficiency.

This refactoring is particularly beneficial, for example when
max_connections and max_locks_per_transaction are set high,
as it reduces unnecessary checks across numerous slots.

Author: Fujii Masao
Reviewed-by: Bertrand Drouvot
Discussion: https://postgr.es/m/a0a00c44-31e9-4c67-9846-fb9636213ac9@oss.nttdata.com

src/backend/storage/lmgr/lock.c

index 09a8ac1578466f320acc8ec219f145a012625811..4fccb7277e1a0624b9ead1cffac5a973351bfe24 100644 (file)
@@ -3731,44 +3731,55 @@ GetLockStatusData(void)
    for (i = 0; i < ProcGlobal->allProcCount; ++i)
    {
        PGPROC     *proc = &ProcGlobal->allProcs[i];
-       uint32      f;
+
+       /* Skip backends with pid=0, as they don't hold fast-path locks */
+       if (proc->pid == 0)
+           continue;
 
        LWLockAcquire(&proc->fpInfoLock, LW_SHARED);
 
-       for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; ++f)
+       for (uint32 g = 0; g < FastPathLockGroupsPerBackend; g++)
        {
-           LockInstanceData *instance;
-           uint32      lockbits = FAST_PATH_GET_BITS(proc, f);
-
-           /* Skip unallocated slots. */
-           if (!lockbits)
+           /* Skip groups without registered fast-path locks */
+           if (proc->fpLockBits[g] == 0)
                continue;
 
-           if (el >= els)
+           for (int j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++)
            {
-               els += MaxBackends;
-               data->locks = (LockInstanceData *)
-                   repalloc(data->locks, sizeof(LockInstanceData) * els);
-           }
+               LockInstanceData *instance;
+               uint32      f = FAST_PATH_SLOT(g, j);
+               uint32      lockbits = FAST_PATH_GET_BITS(proc, f);
 
-           instance = &data->locks[el];
-           SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId,
-                                proc->fpRelId[f]);
-           instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET;
-           instance->waitLockMode = NoLock;
-           instance->vxid.procNumber = proc->vxid.procNumber;
-           instance->vxid.localTransactionId = proc->vxid.lxid;
-           instance->pid = proc->pid;
-           instance->leaderPid = proc->pid;
-           instance->fastpath = true;
+               /* Skip unallocated slots */
+               if (!lockbits)
+                   continue;
 
-           /*
-            * Successfully taking fast path lock means there were no
-            * conflicting locks.
-            */
-           instance->waitStart = 0;
+               if (el >= els)
+               {
+                   els += MaxBackends;
+                   data->locks = (LockInstanceData *)
+                       repalloc(data->locks, sizeof(LockInstanceData) * els);
+               }
 
-           el++;
+               instance = &data->locks[el];
+               SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId,
+                                    proc->fpRelId[f]);
+               instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET;
+               instance->waitLockMode = NoLock;
+               instance->vxid.procNumber = proc->vxid.procNumber;
+               instance->vxid.localTransactionId = proc->vxid.lxid;
+               instance->pid = proc->pid;
+               instance->leaderPid = proc->pid;
+               instance->fastpath = true;
+
+               /*
+                * Successfully taking fast path lock means there were no
+                * conflicting locks.
+                */
+               instance->waitStart = 0;
+
+               el++;
+           }
        }
 
        if (proc->fpVXIDLock)