From cf441fafbc3e778cc353057589ecd038881550ee Mon Sep 17 00:00:00 2001
From: Andrey Borodin <amborodin@acm.org>
Date: Sun, 4 Aug 2024 21:27:59 +0500
Subject: [PATCH v0 2/4] GUCify NUM_BUFFER_PARTITIONS

---
 src/backend/storage/buffer/bufmgr.c           |  8 ++++++++
 src/backend/utils/init/globals.c              |  4 ++++
 src/backend/utils/misc/guc_tables.c           | 10 ++++++++++
 src/backend/utils/misc/postgresql.conf.sample |  1 +
 src/include/storage/buf_internals.h           |  2 +-
 src/include/storage/lwlock.h                  |  4 +++-
 src/include/utils/guc_hooks.h                 |  1 +
 src/test/modules/test_misc/t/003_check_guc.pl |  4 +++-
 8 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 4415ba648a..566f7e85eb 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -57,6 +57,7 @@
 #include "storage/read_stream.h"
 #include "storage/smgr.h"
 #include "storage/standby.h"
+#include "utils/guc_hooks.h"
 #include "utils/memdebug.h"
 #include "utils/ps_status.h"
 #include "utils/rel.h"
@@ -169,6 +170,13 @@ int			bgwriter_lru_maxpages = 100;
 double		bgwriter_lru_multiplier = 2.0;
 bool		track_io_timing = false;
 
+/* GUC assign hook for num_buffer_partitions_log2 */
+void
+assign_num_buffer_partitions_log2(int newval, void *extra)
+{
+	num_buffer_partitions_mask = (1 << newval) - 1;
+}
+
 /*
  * How many buffers PrefetchBuffer callers should try to stay ahead of their
  * ReadBuffer calls by.  Zero means "never prefetch".  This value is only used
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index d8debd160e..c6cdf4a89b 100644
--- a/src/backend/utils/init/globals.c
+++ b/src/backend/utils/init/globals.c
@@ -168,3 +168,7 @@ int			notify_buffers = 16;
 int			serializable_buffers = 32;
 int			subtransaction_buffers = 0;
 int			transaction_buffers = 0;
+
+/* shared buffers partitions number and mask */
+int			num_buffer_partitions_log2 = 7;
+int			num_buffer_partitions_mask = 127;
\ No newline at end of file
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index 74a38bb245..201a7f7947 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -2548,6 +2548,16 @@ struct config_int ConfigureNamesInt[] =
 		check_max_stack_depth, assign_max_stack_depth, NULL
 	},
 
+	{
+		{"num_buffer_partitions_log2", PGC_POSTMASTER, RESOURCES_MEM,
+			gettext_noop("Sets number of partitions for shared buffers mapping hashtable."),
+			NULL,
+		},
+		&num_buffer_partitions_log2,
+		7, 5, 16,
+		NULL, assign_num_buffer_partitions_log2, NULL
+	},
+
 	{
 		{"temp_file_limit", PGC_SUSET, RESOURCES_DISK,
 			gettext_noop("Limits the total size of all temporary files used by each process."),
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 9ec9f97e92..27b1371f38 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -143,6 +143,7 @@
 #autovacuum_work_mem = -1		# min 1MB, or -1 to use maintenance_work_mem
 #logical_decoding_work_mem = 64MB	# min 64kB
 #max_stack_depth = 2MB			# min 100kB
+#num_buffer_partitions_log2 = 7	# number of partitions in shared buffer mapping hashtable
 #shared_memory_type = mmap		# the default is the first option
 					# supported by the operating system:
 					#   mmap
diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h
index fd311a47a2..14421647c2 100644
--- a/src/include/storage/buf_internals.h
+++ b/src/include/storage/buf_internals.h
@@ -180,7 +180,7 @@ static inline LWLock *
 BufMappingPartitionLock(uint32 hashcode)
 {
 	return &MainLWLockArray[BUFFER_MAPPING_LWLOCK_OFFSET +
-							hashcode % NUM_BUFFER_PARTITIONS].lock;
+							(hashcode & num_buffer_partitions_mask)].lock;
 }
 
 /*
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index d70e6d37e0..dad06f37b3 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -90,7 +90,9 @@ extern PGDLLIMPORT int NamedLWLockTrancheRequests;
  */
 
 /* Number of partitions of the shared buffer mapping hashtable */
-#define NUM_BUFFER_PARTITIONS  128
+extern int num_buffer_partitions_log2;
+extern int num_buffer_partitions_mask;
+#define NUM_BUFFER_PARTITIONS  (1 << num_buffer_partitions_log2)
 
 /* Number of partitions the shared lock tables are divided into */
 #define LOG2_NUM_LOCK_PARTITIONS  4
diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h
index 153c652c93..8fd87c70dc 100644
--- a/src/include/utils/guc_hooks.h
+++ b/src/include/utils/guc_hooks.h
@@ -87,6 +87,7 @@ extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
 extern void assign_max_wal_size(int newval, void *extra);
 extern bool check_max_stack_depth(int *newval, void **extra, GucSource source);
 extern void assign_max_stack_depth(int newval, void *extra);
+extern void assign_num_buffer_partitions_log2(int newval, void *extra);
 extern bool check_multixact_member_buffers(int *newval, void **extra,
 										   GucSource source);
 extern bool check_multixact_offset_buffers(int *newval, void **extra,
diff --git a/src/test/modules/test_misc/t/003_check_guc.pl b/src/test/modules/test_misc/t/003_check_guc.pl
index 3ae4bb1cd9..7f6e566af0 100644
--- a/src/test/modules/test_misc/t/003_check_guc.pl
+++ b/src/test/modules/test_misc/t/003_check_guc.pl
@@ -56,8 +56,10 @@ while (my $line = <$contents>)
 	# file.
 	# - Valid configuration options are followed immediately by " = ",
 	# with one space before and after the equal sign.
-	if ($line =~ m/^#?([_[:alpha:]]+) = .*/)
+	print $line;
+	if ($line =~ m/^#?([_[:alnum:]]+) = .*/)
 	{
+		print "da";
 		# Lower-case conversion matters for some of the GUCs.
 		my $param_name = lc($1);
 
-- 
2.39.3 (Apple Git-146)

