From 2a8584ed69c1c492b300ae460c6ce2cf6f8cdb28 Mon Sep 17 00:00:00 2001 From: Anthonin Bonnefoy Date: Tue, 20 Jan 2026 16:34:39 +0100 Subject: Add GUC for checkpointer request queue size Currently, the checkpointer request queue size is auto-tuned to use min(NBuffers, MAX_CHECKPOINT_REQUESTS). Contrary to other auto-tuned subsystems, this setting isn't exposed through a GUC. To make the behaviour consistent with other auto-tuned subsystems, this patch introduces a new checkpoint_request_size GUC with the matching auto-tune function. --- doc/src/sgml/config.sgml | 17 ++++++++ src/backend/postmaster/checkpointer.c | 43 +++++++++++++++---- src/backend/storage/ipc/ipci.c | 1 + src/backend/utils/misc/guc_parameters.dat | 9 ++++ src/backend/utils/misc/postgresql.conf.sample | 1 + src/include/postmaster/bgwriter.h | 4 ++ 6 files changed, 66 insertions(+), 9 deletions(-) diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 5560b95ee60..5a152ee0885 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -3723,6 +3723,23 @@ include_dir 'conf.d' + + checkpoint_request_size (integer) + + checkpoint_request_size configuration parameter + + + + + Specifies the amount of request the checkpointer queue can hold. + The default value is 0, which sets the queue + size to shared_buffers with a cap of 10000000, + to prevent from accumulating too many checkpoint requests. + This parameter can only be set at server start. + + + + checkpoint_warning (integer) diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c index 6482c21b8f9..775f06cfd64 100644 --- a/src/backend/postmaster/checkpointer.c +++ b/src/backend/postmaster/checkpointer.c @@ -148,14 +148,12 @@ static CheckpointerShmemStruct *CheckpointerShmem; /* Maximum number of checkpointer requests to process in one batch */ #define CKPT_REQ_BATCH_SIZE 10000 -/* Max number of requests the checkpointer request queue can hold */ -#define MAX_CHECKPOINT_REQUESTS 10000000 - /* * GUC parameters */ int CheckPointTimeout = 300; int CheckPointWarning = 30; +int CheckPointRequestSize = 0; double CheckPointCompletionTarget = 0.9; /* @@ -958,17 +956,44 @@ CheckpointerShmemSize(void) { Size size; + Assert(CheckPointRequestSize > 0); + + size = offsetof(CheckpointerShmemStruct, requests); + size = add_size(size, mul_size(CheckPointRequestSize, + sizeof(CheckpointerRequest))); + return size; +} + +/* + * Auto-tune checkpoint_request_size based on shared_buffers + */ +void +CheckpointerAutotune(void) +{ + char buf[32]; + + if (CheckPointRequestSize != 0) + return; + /* * The size of the requests[] array is arbitrarily set equal to NBuffers. * But there is a cap of MAX_CHECKPOINT_REQUESTS to prevent accumulating * too many checkpoint requests in the ring buffer. */ - size = offsetof(CheckpointerShmemStruct, requests); - size = add_size(size, mul_size(Min(NBuffers, - MAX_CHECKPOINT_REQUESTS), - sizeof(CheckpointerRequest))); + snprintf(buf, sizeof(buf), "%d", Min(NBuffers, + MAX_CHECKPOINT_REQUESTS)); + SetConfigOption("checkpoint_request_size", buf, PGC_POSTMASTER, + PGC_S_DYNAMIC_DEFAULT); - return size; + /* + * We prefer to report this value's source as PGC_S_DYNAMIC_DEFAULT. + * However, if the DBA explicitly set checkpoint_request_size = 0 in the config file, + * then PGC_S_DYNAMIC_DEFAULT will fail to override that and we must force + * the matter with PGC_S_OVERRIDE. + */ + if (CheckPointRequestSize == 0) /* failed to apply it? */ + SetConfigOption("checkpoint_request_size", buf, PGC_POSTMASTER, + PGC_S_OVERRIDE); } /* @@ -995,7 +1020,7 @@ CheckpointerShmemInit(void) */ MemSet(CheckpointerShmem, 0, size); SpinLockInit(&CheckpointerShmem->ckpt_lck); - CheckpointerShmem->max_requests = Min(NBuffers, MAX_CHECKPOINT_REQUESTS); + CheckpointerShmem->max_requests = CheckPointRequestSize; CheckpointerShmem->head = CheckpointerShmem->tail = 0; ConditionVariableInit(&CheckpointerShmem->start_cv); ConditionVariableInit(&CheckpointerShmem->done_cv); diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index 534d92e7159..a885a6fbe37 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -388,6 +388,7 @@ AutotuneShmem(void) Size requested_size; AioAutotune(); + CheckpointerAutotune(); CLOGAutotune(); CommitTsAutotune(); SUBTRANSAutotune(); diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat index f0260e6e412..48590622b95 100644 --- a/src/backend/utils/misc/guc_parameters.dat +++ b/src/backend/utils/misc/guc_parameters.dat @@ -379,6 +379,15 @@ max => 'WRITEBACK_MAX_PENDING_FLUSHES', }, +{ name => 'checkpoint_request_size', type => 'int', context => 'PGC_SIGHUP', group => 'WAL_CHECKPOINTS', + short_desc => 'Number of requests the checkpointer request queue can hold.', + long_desc => '0 means use the same value as "shared_buffers".', + variable => 'CheckPointRequestSize', + boot_val => '0', + min => '0', + max => 'MAX_CHECKPOINT_REQUESTS', +}, + { name => 'checkpoint_timeout', type => 'int', context => 'PGC_SIGHUP', group => 'WAL_CHECKPOINTS', short_desc => 'Sets the maximum time between automatic WAL checkpoints.', flags => 'GUC_UNIT_S', diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index c4f92fcdac8..256e8040092 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -263,6 +263,7 @@ #checkpoint_timeout = 5min # range 30s-1d #checkpoint_completion_target = 0.9 # checkpoint target duration, 0.0 - 1.0 #checkpoint_flush_after = 0 # measured in pages, 0 disables +#checkpoint_request_size = 0 # 0 sets based on shared_buffers #checkpoint_warning = 30s # 0 disables #max_wal_size = 1GB #min_wal_size = 80MB diff --git a/src/include/postmaster/bgwriter.h b/src/include/postmaster/bgwriter.h index 47470cba893..674d6bbd8fd 100644 --- a/src/include/postmaster/bgwriter.h +++ b/src/include/postmaster/bgwriter.h @@ -21,11 +21,14 @@ #include "storage/smgr.h" #include "storage/sync.h" +/* Max number of requests the checkpointer request queue can hold */ +#define MAX_CHECKPOINT_REQUESTS 10000000 /* GUC options */ extern PGDLLIMPORT int BgWriterDelay; extern PGDLLIMPORT int CheckPointTimeout; extern PGDLLIMPORT int CheckPointWarning; +extern PGDLLIMPORT int CheckPointRequestSize; extern PGDLLIMPORT double CheckPointCompletionTarget; pg_noreturn extern void BackgroundWriterMain(const void *startup_data, size_t startup_data_len); @@ -40,6 +43,7 @@ extern bool ForwardSyncRequest(const FileTag *ftag, SyncRequestType type); extern void AbsorbSyncRequests(void); extern Size CheckpointerShmemSize(void); +extern void CheckpointerAutotune(void); extern void CheckpointerShmemInit(void); extern bool FirstCallSinceLastCheckpoint(void); -- 2.52.0