From ac96535c6f387ff84658b5a3420bd104aa65ced4 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. --- 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 ++ 5 files changed, 49 insertions(+), 9 deletions(-) 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 673a55313f4..88e52664ebe 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -386,6 +386,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