From e11bda7a623728f281e921aff9ba93c5ca299b69 Mon Sep 17 00:00:00 2001 From: Dilip Kumar Date: Wed, 25 Oct 2023 14:45:00 +0530 Subject: [PATCH v7 1/3] Make all SLRU buffer sizes configurable. Provide new GUCs to set the number of buffers, instead of using hard coded defaults. Default sizes are also set to 64 as sizes much larger than the old limits have been shown to be useful on modern systems. Patch by Andrey M. Borodin, Dilip Kumar Reviewed By Anastasia Lubennikova, Tomas Vondra, Alexander Korotkov, Gilles Darold, Thomas Munro --- doc/src/sgml/config.sgml | 135 ++++++++++++++++++ src/backend/access/transam/clog.c | 19 +-- src/backend/access/transam/commit_ts.c | 7 +- src/backend/access/transam/multixact.c | 8 +- src/backend/access/transam/subtrans.c | 5 +- src/backend/commands/async.c | 8 +- src/backend/commands/variable.c | 25 ++++ src/backend/storage/lmgr/predicate.c | 4 +- src/backend/utils/init/globals.c | 8 ++ src/backend/utils/misc/guc_tables.c | 77 ++++++++++ src/backend/utils/misc/postgresql.conf.sample | 9 ++ src/include/access/multixact.h | 4 - src/include/access/slru.h | 5 + src/include/access/subtrans.h | 3 - src/include/commands/async.h | 5 - src/include/miscadmin.h | 7 + src/include/storage/predicate.h | 4 - src/include/utils/guc_hooks.h | 2 + 18 files changed, 293 insertions(+), 42 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 9398afbcbd..bcbae61bb3 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -2006,6 +2006,141 @@ include_dir 'conf.d' + + multixact_offsets_buffers (integer) + + multixact_offsets_buffers configuration parameter + + + + + Specifies the amount of shared memory to use to cache the contents + of pg_multixact/offsets (see + ). + If this value is specified without units, it is taken as blocks, + that is BLCKSZ bytes, typically 8kB. + The default value is 64. + This parameter can only be set at server start. + + + + + + multixact_members_buffers (integer) + + multixact_members_buffers configuration parameter + + + + + Specifies the amount of shared memory to use to cache the contents + of pg_multixact/members (see + ). + If this value is specified without units, it is taken as blocks, + that is BLCKSZ bytes, typically 8kB. + The default value is 64. + This parameter can only be set at server start. + + + + + + subtrans_buffers (integer) + + subtrans_buffers configuration parameter + + + + + Specifies the amount of shared memory to use to cache the contents + of pg_subtrans (see + ). + If this value is specified without units, it is taken as blocks, + that is BLCKSZ bytes, typically 8kB. + The default value is 64. + This parameter can only be set at server start. + + + + + + notify_buffers (integer) + + notify_buffers configuration parameter + + + + + Specifies the amount of shared memory to use to cache the contents + of pg_notify (see + ). + If this value is specified without units, it is taken as blocks, + that is BLCKSZ bytes, typically 8kB. + The default value is 64. + This parameter can only be set at server start. + + + + + + serial_buffers (integer) + + serial_buffers configuration parameter + + + + + Specifies the amount of shared memory to use to cache the contents + of pg_serial (see + ). + If this value is specified without units, it is taken as blocks, + that is BLCKSZ bytes, typically 8kB. + The default value is 64. + This parameter can only be set at server start. + + + + + + xact_buffers (integer) + + xact_buffers configuration parameter + + + + + Specifies the amount of shared memory to use to cache the contents + of pg_xact (see + ). + If this value is specified without units, it is taken as blocks, + that is BLCKSZ bytes, typically 8kB. + The default value is 0, which requests + shared_buffers / 512, but not fewer than 16 blocks. + This parameter can only be set at server start. + + + + + + commit_ts_buffers (integer) + + commit_ts_buffers configuration parameter + + + + + Specifies the amount of memory to use to cache the contents of + pg_commit_ts (see + ). + If this value is specified without units, it is taken as blocks, + that is BLCKSZ bytes, typically 8kB. + The default value is 0, which requests + shared_buffers / 256, but not fewer than 16 blocks. + This parameter can only be set at server start. + + + + max_stack_depth (integer) diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index 4a431d5876..8237b40aa6 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -663,23 +663,16 @@ TransactionIdGetStatus(TransactionId xid, XLogRecPtr *lsn) /* * Number of shared CLOG buffers. * - * On larger multi-processor systems, it is possible to have many CLOG page - * requests in flight at one time which could lead to disk access for CLOG - * page if the required page is not found in memory. Testing revealed that we - * can get the best performance by having 128 CLOG buffers, more than that it - * doesn't improve performance. - * - * Unconditionally keeping the number of CLOG buffers to 128 did not seem like - * a good idea, because it would increase the minimum amount of shared memory - * required to start, which could be a problem for people running very small - * configurations. The following formula seems to represent a reasonable - * compromise: people with very low values for shared_buffers will get fewer - * CLOG buffers as well, and everyone else will get 128. + * By default, we'll use 2MB of for every 1GB of shared buffers, up to the + * maximum value that slru.c will allow, but always at least 16 buffers. */ Size CLOGShmemBuffers(void) { - return Min(128, Max(4, NBuffers / 512)); + /* Use configured value if provided. */ + if (xact_buffers > 0) + return Max(16, xact_buffers); + return Min(SLRU_MAX_ALLOWED_BUFFERS, Max(16, NBuffers / 512)); } /* diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c index b897fabc70..9ba5ae6534 100644 --- a/src/backend/access/transam/commit_ts.c +++ b/src/backend/access/transam/commit_ts.c @@ -493,11 +493,16 @@ pg_xact_commit_timestamp_origin(PG_FUNCTION_ARGS) * We use a very similar logic as for the number of CLOG buffers (except we * scale up twice as fast with shared buffers, and the maximum is twice as * high); see comments in CLOGShmemBuffers. + * By default, we'll use 4MB of for every 1GB of shared buffers, up to the + * maximum value that slru.c will allow, but always at least 16 buffers. */ Size CommitTsShmemBuffers(void) { - return Min(256, Max(4, NBuffers / 256)); + /* Use configured value if provided. */ + if (commit_ts_buffers > 0) + return Max(16, commit_ts_buffers); + return Min(256, Max(16, NBuffers / 256)); } /* diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index 57ed34c0a8..62709fcd07 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1834,8 +1834,8 @@ MultiXactShmemSize(void) mul_size(sizeof(MultiXactId) * 2, MaxOldestSlot)) size = SHARED_MULTIXACT_STATE_SIZE; - size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTOFFSET_BUFFERS, 0)); - size = add_size(size, SimpleLruShmemSize(NUM_MULTIXACTMEMBER_BUFFERS, 0)); + size = add_size(size, SimpleLruShmemSize(multixact_offsets_buffers, 0)); + size = add_size(size, SimpleLruShmemSize(multixact_members_buffers, 0)); return size; } @@ -1851,13 +1851,13 @@ MultiXactShmemInit(void) MultiXactMemberCtl->PagePrecedes = MultiXactMemberPagePrecedes; SimpleLruInit(MultiXactOffsetCtl, - "MultiXactOffset", NUM_MULTIXACTOFFSET_BUFFERS, 0, + "MultiXactOffset", multixact_offsets_buffers, 0, MultiXactOffsetSLRULock, "pg_multixact/offsets", LWTRANCHE_MULTIXACTOFFSET_BUFFER, SYNC_HANDLER_MULTIXACT_OFFSET); SlruPagePrecedesUnitTests(MultiXactOffsetCtl, MULTIXACT_OFFSETS_PER_PAGE); SimpleLruInit(MultiXactMemberCtl, - "MultiXactMember", NUM_MULTIXACTMEMBER_BUFFERS, 0, + "MultiXactMember", multixact_members_buffers, 0, MultiXactMemberSLRULock, "pg_multixact/members", LWTRANCHE_MULTIXACTMEMBER_BUFFER, SYNC_HANDLER_MULTIXACT_MEMBER); diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c index 62bb610167..0dd48f40f3 100644 --- a/src/backend/access/transam/subtrans.c +++ b/src/backend/access/transam/subtrans.c @@ -31,6 +31,7 @@ #include "access/slru.h" #include "access/subtrans.h" #include "access/transam.h" +#include "miscadmin.h" #include "pg_trace.h" #include "utils/snapmgr.h" @@ -184,14 +185,14 @@ SubTransGetTopmostTransaction(TransactionId xid) Size SUBTRANSShmemSize(void) { - return SimpleLruShmemSize(NUM_SUBTRANS_BUFFERS, 0); + return SimpleLruShmemSize(subtrans_buffers, 0); } void SUBTRANSShmemInit(void) { SubTransCtl->PagePrecedes = SubTransPagePrecedes; - SimpleLruInit(SubTransCtl, "Subtrans", NUM_SUBTRANS_BUFFERS, 0, + SimpleLruInit(SubTransCtl, "Subtrans", subtrans_buffers, 0, SubtransSLRULock, "pg_subtrans", LWTRANCHE_SUBTRANS_BUFFER, SYNC_HANDLER_NONE); SlruPagePrecedesUnitTests(SubTransCtl, SUBTRANS_XACTS_PER_PAGE); diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 38ddae08b8..4bdbbe5cc0 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -117,7 +117,7 @@ * frontend during startup.) The above design guarantees that notifies from * other backends will never be missed by ignoring self-notifies. * - * The amount of shared memory used for notify management (NUM_NOTIFY_BUFFERS) + * The amount of shared memory used for notify management (notify_buffers) * can be varied without affecting anything but performance. The maximum * amount of notification data that can be queued at one time is determined * by slru.c's wraparound limit; see QUEUE_MAX_PAGE below. @@ -235,7 +235,7 @@ typedef struct QueuePosition * * Resist the temptation to make this really large. While that would save * work in some places, it would add cost in others. In particular, this - * should likely be less than NUM_NOTIFY_BUFFERS, to ensure that backends + * should likely be less than notify_buffers, to ensure that backends * catch up before the pages they'll need to read fall out of SLRU cache. */ #define QUEUE_CLEANUP_DELAY 4 @@ -521,7 +521,7 @@ AsyncShmemSize(void) size = mul_size(MaxBackends + 1, sizeof(QueueBackendStatus)); size = add_size(size, offsetof(AsyncQueueControl, backend)); - size = add_size(size, SimpleLruShmemSize(NUM_NOTIFY_BUFFERS, 0)); + size = add_size(size, SimpleLruShmemSize(notify_buffers, 0)); return size; } @@ -569,7 +569,7 @@ AsyncShmemInit(void) * Set up SLRU management of the pg_notify data. */ NotifyCtl->PagePrecedes = asyncQueuePagePrecedes; - SimpleLruInit(NotifyCtl, "Notify", NUM_NOTIFY_BUFFERS, 0, + SimpleLruInit(NotifyCtl, "Notify", notify_buffers, 0, NotifySLRULock, "pg_notify", LWTRANCHE_NOTIFY_BUFFER, SYNC_HANDLER_NONE); diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index a88cf5f118..c68d668514 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -18,6 +18,8 @@ #include +#include "access/clog.h" +#include "access/commit_ts.h" #include "access/htup_details.h" #include "access/parallel.h" #include "access/xact.h" @@ -400,6 +402,29 @@ show_timezone(void) return "unknown"; } +/* + * GUC show_hook for xact_buffers + */ +const char * +show_xact_buffers(void) +{ + static char nbuf[16]; + + snprintf(nbuf, sizeof(nbuf), "%zu", CLOGShmemBuffers()); + return nbuf; +} + +/* + * GUC show_hook for commit_ts_buffers + */ +const char * +show_commit_ts_buffers(void) +{ + static char nbuf[16]; + + snprintf(nbuf, sizeof(nbuf), "%zu", CommitTsShmemBuffers()); + return nbuf; +} /* * LOG_TIMEZONE diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index a794546db3..18ea18316d 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -808,7 +808,7 @@ SerialInit(void) */ SerialSlruCtl->PagePrecedes = SerialPagePrecedesLogically; SimpleLruInit(SerialSlruCtl, "Serial", - NUM_SERIAL_BUFFERS, 0, SerialSLRULock, "pg_serial", + serial_buffers, 0, SerialSLRULock, "pg_serial", LWTRANCHE_SERIAL_BUFFER, SYNC_HANDLER_NONE); #ifdef USE_ASSERT_CHECKING SerialPagePrecedesLogicallyUnitTests(); @@ -1347,7 +1347,7 @@ PredicateLockShmemSize(void) /* Shared memory structures for SLRU tracking of old committed xids. */ size = add_size(size, sizeof(SerialControlData)); - size = add_size(size, SimpleLruShmemSize(NUM_SERIAL_BUFFERS, 0)); + size = add_size(size, SimpleLruShmemSize(serial_buffers, 0)); return size; } diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 60bc1217fb..96d480325b 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -156,3 +156,11 @@ int64 VacuumPageDirty = 0; int VacuumCostBalance = 0; /* working state for vacuum */ bool VacuumCostActive = false; + +int multixact_offsets_buffers = 64; +int multixact_members_buffers = 64; +int subtrans_buffers = 64; +int notify_buffers = 64; +int serial_buffers = 64; +int xact_buffers = 64; +int commit_ts_buffers = 64; diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index b764ef6998..c1345dab98 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -28,6 +28,7 @@ #include "access/commit_ts.h" #include "access/gin.h" +#include "access/slru.h" #include "access/toast_compression.h" #include "access/twophase.h" #include "access/xlog_internal.h" @@ -2287,6 +2288,82 @@ struct config_int ConfigureNamesInt[] = NULL, NULL, NULL }, + { + {"multixact_offsets_buffers", PGC_POSTMASTER, RESOURCES_MEM, + gettext_noop("Sets the number of shared memory buffers used for the MultiXact offset SLRU cache."), + NULL, + GUC_UNIT_BLOCKS + }, + &multixact_offsets_buffers, + 64, 16, SLRU_MAX_ALLOWED_BUFFERS, + NULL, NULL, NULL + }, + + { + {"multixact_members_buffers", PGC_POSTMASTER, RESOURCES_MEM, + gettext_noop("Sets the number of shared memory buffers used for the MultiXact member SLRU cache."), + NULL, + GUC_UNIT_BLOCKS + }, + &multixact_members_buffers, + 64, 16, SLRU_MAX_ALLOWED_BUFFERS, + NULL, NULL, NULL + }, + + { + {"subtrans_buffers", PGC_POSTMASTER, RESOURCES_MEM, + gettext_noop("Sets the number of shared memory buffers used for the sub-transaction SLRU cache."), + NULL, + GUC_UNIT_BLOCKS + }, + &subtrans_buffers, + 64, 16, SLRU_MAX_ALLOWED_BUFFERS, + NULL, NULL, NULL + }, + { + {"notify_buffers", PGC_POSTMASTER, RESOURCES_MEM, + gettext_noop("Sets the number of shared memory buffers used for the NOTIFY message SLRU cache."), + NULL, + GUC_UNIT_BLOCKS + }, + ¬ify_buffers, + 64, 16, SLRU_MAX_ALLOWED_BUFFERS, + NULL, NULL, NULL + }, + + { + {"serial_buffers", PGC_POSTMASTER, RESOURCES_MEM, + gettext_noop("Sets the number of shared memory buffers used for the serializable transaction SLRU cache."), + NULL, + GUC_UNIT_BLOCKS + }, + &serial_buffers, + 64, 16, SLRU_MAX_ALLOWED_BUFFERS, + NULL, NULL, NULL + }, + + { + {"xact_buffers", PGC_POSTMASTER, RESOURCES_MEM, + gettext_noop("Sets the number of shared memory buffers used for the transaction status SLRU cache."), + NULL, + GUC_UNIT_BLOCKS + }, + &xact_buffers, + 64, 0, SLRU_MAX_ALLOWED_BUFFERS, + NULL, NULL, show_xact_buffers + }, + + { + {"commit_ts_buffers", PGC_POSTMASTER, RESOURCES_MEM, + gettext_noop("Sets the size of the dedicated buffer pool used for the commit timestamp SLRU cache."), + NULL, + GUC_UNIT_BLOCKS + }, + &commit_ts_buffers, + 64, 0, SLRU_MAX_ALLOWED_BUFFERS, + NULL, NULL, show_commit_ts_buffers + }, + { {"temp_buffers", PGC_USERSET, RESOURCES_MEM, gettext_noop("Sets the maximum number of temporary buffers used by each session."), diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index e48c066a5b..364553a314 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -50,6 +50,15 @@ #external_pid_file = '' # write an extra PID file # (change requires restart) +# - SLRU Buffers (change requires restart) - + +#xact_buffers = 0 # memory for pg_xact (0 = auto) +#subtrans_buffers = 64 # memory for pg_subtrans +#multixact_offsets_buffers = 64 # memory for pg_multixact/offsets +#multixact_members_buffers = 64 # memory for pg_multixact/members +#notify_buffers = 64 # memory for pg_notify +#serial_buffers = 64 # memory for pg_serial +#commit_ts_buffers = 0 # memory for pg_commit_ts (0 = auto) #------------------------------------------------------------------------------ # CONNECTIONS AND AUTHENTICATION diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h index 0be1355892..18d7ba4ca9 100644 --- a/src/include/access/multixact.h +++ b/src/include/access/multixact.h @@ -29,10 +29,6 @@ #define MaxMultiXactOffset ((MultiXactOffset) 0xFFFFFFFF) -/* Number of SLRU buffers to use for multixact */ -#define NUM_MULTIXACTOFFSET_BUFFERS 8 -#define NUM_MULTIXACTMEMBER_BUFFERS 16 - /* * Possible multixact lock modes ("status"). The first four modes are for * tuple locks (FOR KEY SHARE, FOR SHARE, FOR NO KEY UPDATE, FOR UPDATE); the diff --git a/src/include/access/slru.h b/src/include/access/slru.h index 552cc19e68..c0d37e3eb3 100644 --- a/src/include/access/slru.h +++ b/src/include/access/slru.h @@ -17,6 +17,11 @@ #include "storage/lwlock.h" #include "storage/sync.h" +/* + * To avoid overflowing internal arithmetic and the size_t data type, the + * number of buffers should not exceed this number. + */ +#define SLRU_MAX_ALLOWED_BUFFERS ((1024 * 1024 * 1024) / BLCKSZ) /* * Define SLRU segment size. A page is the same BLCKSZ as is used everywhere diff --git a/src/include/access/subtrans.h b/src/include/access/subtrans.h index 46a473c77f..147dc4acc3 100644 --- a/src/include/access/subtrans.h +++ b/src/include/access/subtrans.h @@ -11,9 +11,6 @@ #ifndef SUBTRANS_H #define SUBTRANS_H -/* Number of SLRU buffers to use for subtrans */ -#define NUM_SUBTRANS_BUFFERS 32 - extern void SubTransSetParent(TransactionId xid, TransactionId parent); extern TransactionId SubTransGetParent(TransactionId xid); extern TransactionId SubTransGetTopmostTransaction(TransactionId xid); diff --git a/src/include/commands/async.h b/src/include/commands/async.h index 02da6ba7e1..b3e6815ee4 100644 --- a/src/include/commands/async.h +++ b/src/include/commands/async.h @@ -15,11 +15,6 @@ #include -/* - * The number of SLRU page buffers we use for the notification queue. - */ -#define NUM_NOTIFY_BUFFERS 8 - extern PGDLLIMPORT bool Trace_notify; extern PGDLLIMPORT volatile sig_atomic_t notifyInterruptPending; diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index f0cc651435..e2473f41de 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -177,6 +177,13 @@ extern PGDLLIMPORT int MaxBackends; extern PGDLLIMPORT int MaxConnections; extern PGDLLIMPORT int max_worker_processes; extern PGDLLIMPORT int max_parallel_workers; +extern PGDLLIMPORT int multixact_offsets_buffers; +extern PGDLLIMPORT int multixact_members_buffers; +extern PGDLLIMPORT int subtrans_buffers; +extern PGDLLIMPORT int notify_buffers; +extern PGDLLIMPORT int serial_buffers; +extern PGDLLIMPORT int xact_buffers; +extern PGDLLIMPORT int commit_ts_buffers; extern PGDLLIMPORT int MyProcPid; extern PGDLLIMPORT pg_time_t MyStartTime; diff --git a/src/include/storage/predicate.h b/src/include/storage/predicate.h index cd48afa17b..7b68c8f1c7 100644 --- a/src/include/storage/predicate.h +++ b/src/include/storage/predicate.h @@ -26,10 +26,6 @@ extern PGDLLIMPORT int max_predicate_locks_per_xact; extern PGDLLIMPORT int max_predicate_locks_per_relation; extern PGDLLIMPORT int max_predicate_locks_per_page; - -/* Number of SLRU buffers to use for Serial SLRU */ -#define NUM_SERIAL_BUFFERS 16 - /* * A handle used for sharing SERIALIZABLEXACT objects between the participants * in a parallel query. diff --git a/src/include/utils/guc_hooks.h b/src/include/utils/guc_hooks.h index 3d74483f44..7b95acf36e 100644 --- a/src/include/utils/guc_hooks.h +++ b/src/include/utils/guc_hooks.h @@ -163,4 +163,6 @@ extern void assign_wal_consistency_checking(const char *newval, void *extra); extern bool check_wal_segment_size(int *newval, void **extra, GucSource source); extern void assign_wal_sync_method(int new_wal_sync_method, void *extra); +extern const char *show_xact_buffers(void); +extern const char *show_commit_ts_buffers(void); #endif /* GUC_HOOKS_H */ -- 2.39.2 (Apple Git-143)