Skip to content

Commit 9364574

Browse files
committed
Eliminate divide in new fast-path locking code
c4d5cb7 adjusted the fast-path locking code to allow some configuration of the number of fast-path locking slots via the max_locks_per_transaction GUC. In that commit the FAST_PATH_REL_GROUP() macro used integer division to determine the fast-path locking group slot to use for the lock. The divisor in this case is always a power-of-two value. Here we swap out the divide by a bitwise-AND, which is a significantly faster operation to perform. In passing, adjust the code that's setting FastPathLockGroupsPerBackend so that it's more clear that the value being set is a power-of-two. Also, adjust some comments in the area which contained some magic numbers. It seems better to justify the 1024 upper limit in the location where the #define is made instead of where it is used. Author: David Rowley <drowleyml@gmail.com> Reviewed-by: Tomas Vondra <tomas@vondra.me> Discussion: https://postgr.es/m/CAApHDvodr3bcnpxcs7+k-3cFwYR0tP-BYhyd2PpDhe-bCx9i=g@mail.gmail.com
1 parent 2775767 commit 9364574

File tree

3 files changed

+27
-20
lines changed

3 files changed

+27
-20
lines changed

src/backend/storage/lmgr/lock.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,9 +210,12 @@ int FastPathLockGroupsPerBackend = 0;
210210
*
211211
* The selected constant (49157) is a prime not too close to 2^k, and it's
212212
* small enough to not cause overflows (in 64-bit).
213+
*
214+
* We can assume that FastPathLockGroupsPerBackend is a power-of-two per
215+
* InitializeFastPathLocks().
213216
*/
214217
#define FAST_PATH_REL_GROUP(rel) \
215-
(((uint64) (rel) * 49157) % FastPathLockGroupsPerBackend)
218+
(((uint64) (rel) * 49157) & (FastPathLockGroupsPerBackend - 1))
216219

217220
/*
218221
* Given the group/slot indexes, calculate the slot index in the whole array

src/backend/utils/init/postinit.c

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -575,33 +575,29 @@ InitializeMaxBackends(void)
575575
*
576576
* This must be called after modules have had the chance to alter GUCs in
577577
* shared_preload_libraries and before shared memory size is determined.
578-
*
579-
* The default max_locks_per_xact=64 means 4 groups by default.
580-
*
581-
* We allow anything between 1 and 1024 groups, with the usual power-of-2
582-
* logic. The 1 is the "old" size with only 16 slots, 1024 is an arbitrary
583-
* limit (matching max_locks_per_xact = 16k). Values over 1024 are unlikely
584-
* to be beneficial - there are bottlenecks we'll hit way before that.
585578
*/
586579
void
587580
InitializeFastPathLocks(void)
588581
{
589582
/* Should be initialized only once. */
590583
Assert(FastPathLockGroupsPerBackend == 0);
591584

592-
/* we need at least one group */
593-
FastPathLockGroupsPerBackend = 1;
594-
595-
while (FastPathLockGroupsPerBackend < FP_LOCK_GROUPS_PER_BACKEND_MAX)
596-
{
597-
/* stop once we exceed max_locks_per_xact */
598-
if (FastPathLockSlotsPerBackend() >= max_locks_per_xact)
599-
break;
600-
601-
FastPathLockGroupsPerBackend *= 2;
602-
}
585+
/*
586+
* Based on the max_locks_per_transaction GUC, as that's a good indicator
587+
* of the expected number of locks, figure out the value for
588+
* FastPathLockGroupsPerBackend. This must be a power-of-two. We cap the
589+
* value at FP_LOCK_GROUPS_PER_BACKEND_MAX and insist the value is at
590+
* least 1.
591+
*
592+
* The default max_locks_per_transaction = 64 means 4 groups by default.
593+
*/
594+
FastPathLockGroupsPerBackend =
595+
Max(Min(pg_nextpower2_32(max_locks_per_xact) / FP_LOCK_SLOTS_PER_GROUP,
596+
FP_LOCK_GROUPS_PER_BACKEND_MAX), 1);
603597

604-
Assert(FastPathLockGroupsPerBackend <= FP_LOCK_GROUPS_PER_BACKEND_MAX);
598+
/* Validate we did get a power-of-two */
599+
Assert(FastPathLockGroupsPerBackend ==
600+
pg_nextpower2_32(FastPathLockGroupsPerBackend));
605601
}
606602

607603
/*

src/include/storage/proc.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ struct XidCache
8686
*/
8787
extern PGDLLIMPORT int FastPathLockGroupsPerBackend;
8888

89+
/*
90+
* Define the maximum number of fast-path locking groups per backend.
91+
* This must be a power-of-two value. The actual number of fast-path
92+
* lock groups is calculated in InitializeFastPathLocks() based on
93+
* max_locks_per_transaction. 1024 is an arbitrary upper limit (matching
94+
* max_locks_per_transaction = 16k). Values over 1024 are unlikely to be
95+
* beneficial as there are bottlenecks we'll hit way before that.
96+
*/
8997
#define FP_LOCK_GROUPS_PER_BACKEND_MAX 1024
9098
#define FP_LOCK_SLOTS_PER_GROUP 16 /* don't change */
9199
#define FastPathLockSlotsPerBackend() \

0 commit comments

Comments
 (0)