aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/init/postinit.c
diff options
context:
space:
mode:
authorDavid Rowley <drowley@postgresql.org>2025-04-27 11:53:40 +1200
committerDavid Rowley <drowley@postgresql.org>2025-04-27 11:53:40 +1200
commit936457419d797dfaf37191db53d5efb1279eae6d (patch)
treece4ab746e8e814bd18bad3bd561391a4ff0d5382 /src/backend/utils/init/postinit.c
parent27757677ca4da566ff21f65c58a008818afb5b06 (diff)
downloadpostgresql-936457419d797dfaf37191db53d5efb1279eae6d.tar.gz
postgresql-936457419d797dfaf37191db53d5efb1279eae6d.zip
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
Diffstat (limited to 'src/backend/utils/init/postinit.c')
-rw-r--r--src/backend/utils/init/postinit.c34
1 files changed, 15 insertions, 19 deletions
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index 01309ef3f86..28f09a27001 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -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;
-
- 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;
- }
+ /*
+ * 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);
- Assert(FastPathLockGroupsPerBackend <= FP_LOCK_GROUPS_PER_BACKEND_MAX);
+ /* Validate we did get a power-of-two */
+ Assert(FastPathLockGroupsPerBackend ==
+ pg_nextpower2_32(FastPathLockGroupsPerBackend));
}
/*