From 0f640c042458b98c6b7fbd9360561c3623b8d9c7 Mon Sep 17 00:00:00 2001 From: Nazir Bilal Yavuz Date: Mon, 31 Mar 2025 12:21:27 +0300 Subject: [PATCH v8 2/3] Count free buffers at the start of the autoprewarm Streamified version of the autoprewarm code may do unnecessary I/O and buffer evicting. To prevent it at least a little bit, count the number of free buffers in the buffer pool and queue buffers up to that number in the callback function of the autoprewarm. --- contrib/pg_prewarm/autoprewarm.c | 5 ++++- src/backend/storage/buffer/freelist.c | 17 +++++++++++++++++ src/include/storage/buf_internals.h | 1 + 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c index 7154303f0ba..4f635eaf31c 100644 --- a/contrib/pg_prewarm/autoprewarm.c +++ b/contrib/pg_prewarm/autoprewarm.c @@ -518,6 +518,7 @@ void autoprewarm_database_main(Datum main_arg) { int pos; + int stop_idx; BlockInfoRecord *block_info; Relation rel = NULL; dsm_segment *seg; @@ -538,6 +539,8 @@ autoprewarm_database_main(Datum main_arg) BackgroundWorkerInitializeConnectionByOid(apw_state->database, InvalidOid, 0); block_info = (BlockInfoRecord *) dsm_segment_address(seg); pos = apw_state->prewarm_start_idx; + stop_idx = Min(apw_state->prewarm_stop_idx, + pos + get_number_of_free_buffers()); cur_database = block_info[pos].database; @@ -545,7 +548,7 @@ autoprewarm_database_main(Datum main_arg) * Loop until we run out of blocks to prewarm or until we run out of free * buffers. */ - while (pos < apw_state->prewarm_stop_idx && have_free_buffer()) + while (pos < stop_idx && have_free_buffer()) { BlockInfoRecord *blk = &block_info[pos]; diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c index 336715b6c63..9f26e940426 100644 --- a/src/backend/storage/buffer/freelist.c +++ b/src/backend/storage/buffer/freelist.c @@ -180,6 +180,23 @@ have_free_buffer(void) return false; } +/* + * get_number_of_free_buffers -- a lockless way to get the number of free + * buffers in buffer pool. + * + * Note that result continuously changes as free buffers are moved out by other + * operations. + */ +int +get_number_of_free_buffers(void) +{ + /* All the buffers are free. */ + if (StrategyControl->firstFreeBuffer < 0) + return NBuffers; + else + return StrategyControl->lastFreeBuffer - StrategyControl->firstFreeBuffer; +} + /* * StrategyGetBuffer * diff --git a/src/include/storage/buf_internals.h b/src/include/storage/buf_internals.h index 72b36a4af26..cdc9936fccd 100644 --- a/src/include/storage/buf_internals.h +++ b/src/include/storage/buf_internals.h @@ -448,6 +448,7 @@ extern void StrategyNotifyBgWriter(int bgwprocno); extern Size StrategyShmemSize(void); extern void StrategyInitialize(bool init); extern bool have_free_buffer(void); +extern int get_number_of_free_buffers(void); /* buf_table.c */ extern Size BufTableShmemSize(int size); -- 2.43.0