From: Fujii Masao <masao.fujii@oss.nttdata.com>
To: pgsql-hackers@postgresql.org
Subject: Refactor GetLockStatusData() by skipping unused backends and groups
Date: Mon, 21 Oct 2024 09:19:49 +0900
Message-ID: <a0a00c44-31e9-4c67-9846-fb9636213ac9@oss.nttdata.com> (raw)
Hi,
While reading the fast-path lock code, I noticed that GetLockStatusData()
checks all slots for every backend to gather fast-path lock data. However,
backends with PID=0 don't hold fast-path locks, right? If so, we can
improve efficiency by having GetLockStatusData() skip those backends early.
Additionally, when GetLockStatusData() checks a backend, it currently
goes through all the slots accross its groups. Each group has 16 slots,
so if a backend has 4 groups (this can change depending on max_locks_per_transaction),
that means checking 64 slots. Instead, we could refactor the function
to skip groups without registered fast-path locks, improving performance.
Since each set of 16 slots is packed into a uint32 variable (PGPROC->fpLockBits[i]),
it’s easy to check if a group has any fast-path locks.
I've attached a patch that implements these changes. This refactoring is
especially useful when max_connections and max_locks_per_transaction are
set high, as it reduces unnecessary checks across numerous slots.
Regards,
--
Fujii Masao
Advanced Computing Technology Center
Research and Development Headquarters
NTT DATA CORPORATION
Attachments:v1-0001-Refactor-GetLockStatusData-to-skip-backends-group.patch (text/plain, 3.4K) download
From 2f4c1f51ccd32981a1bfefe04468e630cb0bd63c Mon Sep 17 00:00:00 2001
From: Fujii Masao <fujii@postgresql.org>
Date: Sun, 20 Oct 2024 14:51:07 +0900
Subject: [PATCH v1] Refactor GetLockStatusData() to skip backends/groups
without fast-path locks.
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.
---
src/backend/storage/lmgr/lock.c | 67 +++++++++++++++++++--------------
1 file changed, 39 insertions(+), 28 deletions(-)
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.cindex 09a8ac1578..4ea47f2d99 100644--- a/src/backend/storage/lmgr/lock.c+++ b/src/backend/storage/lmgr/lock.c@@ -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 unallocated groups */+ 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)
--
2.46.2
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: masao.fujii@oss.nttdata.com
Subject: Re: Refactor GetLockStatusData() by skipping unused backends and groups
In-Reply-To: <a0a00c44-31e9-4c67-9846-fb9636213ac9@oss.nttdata.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox