mirror of
https://github.com/postgres/postgres.git
synced 2025-05-29 16:21:20 +03:00
Eliminate divide in new fast-path locking code
c4d5cb71d2 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
This commit is contained in:
parent
27757677ca
commit
936457419d
@ -210,9 +210,12 @@ int FastPathLockGroupsPerBackend = 0;
|
||||
*
|
||||
* The selected constant (49157) is a prime not too close to 2^k, and it's
|
||||
* small enough to not cause overflows (in 64-bit).
|
||||
*
|
||||
* We can assume that FastPathLockGroupsPerBackend is a power-of-two per
|
||||
* InitializeFastPathLocks().
|
||||
*/
|
||||
#define FAST_PATH_REL_GROUP(rel) \
|
||||
(((uint64) (rel) * 49157) % FastPathLockGroupsPerBackend)
|
||||
(((uint64) (rel) * 49157) & (FastPathLockGroupsPerBackend - 1))
|
||||
|
||||
/*
|
||||
* Given the group/slot indexes, calculate the slot index in the whole array
|
||||
|
@ -575,13 +575,6 @@ InitializeMaxBackends(void)
|
||||
*
|
||||
* This must be called after modules have had the chance to alter GUCs in
|
||||
* shared_preload_libraries and before shared memory size is determined.
|
||||
*
|
||||
* The default max_locks_per_xact=64 means 4 groups by default.
|
||||
*
|
||||
* We allow anything between 1 and 1024 groups, with the usual power-of-2
|
||||
* logic. The 1 is the "old" size with only 16 slots, 1024 is an arbitrary
|
||||
* limit (matching max_locks_per_xact = 16k). Values over 1024 are unlikely
|
||||
* to be beneficial - there are bottlenecks we'll hit way before that.
|
||||
*/
|
||||
void
|
||||
InitializeFastPathLocks(void)
|
||||
@ -589,19 +582,22 @@ InitializeFastPathLocks(void)
|
||||
/* Should be initialized only once. */
|
||||
Assert(FastPathLockGroupsPerBackend == 0);
|
||||
|
||||
/* we need at least one group */
|
||||
FastPathLockGroupsPerBackend = 1;
|
||||
/*
|
||||
* Based on the max_locks_per_transaction GUC, as that's a good indicator
|
||||
* of the expected number of locks, figure out the value for
|
||||
* FastPathLockGroupsPerBackend. This must be a power-of-two. We cap the
|
||||
* value at FP_LOCK_GROUPS_PER_BACKEND_MAX and insist the value is at
|
||||
* least 1.
|
||||
*
|
||||
* The default max_locks_per_transaction = 64 means 4 groups by default.
|
||||
*/
|
||||
FastPathLockGroupsPerBackend =
|
||||
Max(Min(pg_nextpower2_32(max_locks_per_xact) / FP_LOCK_SLOTS_PER_GROUP,
|
||||
FP_LOCK_GROUPS_PER_BACKEND_MAX), 1);
|
||||
|
||||
while (FastPathLockGroupsPerBackend < FP_LOCK_GROUPS_PER_BACKEND_MAX)
|
||||
{
|
||||
/* stop once we exceed max_locks_per_xact */
|
||||
if (FastPathLockSlotsPerBackend() >= max_locks_per_xact)
|
||||
break;
|
||||
|
||||
FastPathLockGroupsPerBackend *= 2;
|
||||
}
|
||||
|
||||
Assert(FastPathLockGroupsPerBackend <= FP_LOCK_GROUPS_PER_BACKEND_MAX);
|
||||
/* Validate we did get a power-of-two */
|
||||
Assert(FastPathLockGroupsPerBackend ==
|
||||
pg_nextpower2_32(FastPathLockGroupsPerBackend));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -86,6 +86,14 @@ struct XidCache
|
||||
*/
|
||||
extern PGDLLIMPORT int FastPathLockGroupsPerBackend;
|
||||
|
||||
/*
|
||||
* Define the maximum number of fast-path locking groups per backend.
|
||||
* This must be a power-of-two value. The actual number of fast-path
|
||||
* lock groups is calculated in InitializeFastPathLocks() based on
|
||||
* max_locks_per_transaction. 1024 is an arbitrary upper limit (matching
|
||||
* max_locks_per_transaction = 16k). Values over 1024 are unlikely to be
|
||||
* beneficial as there are bottlenecks we'll hit way before that.
|
||||
*/
|
||||
#define FP_LOCK_GROUPS_PER_BACKEND_MAX 1024
|
||||
#define FP_LOCK_SLOTS_PER_GROUP 16 /* don't change */
|
||||
#define FastPathLockSlotsPerBackend() \
|
||||
|
Loading…
x
Reference in New Issue
Block a user