v11-0001-Autoprewarm-global-objects-separately.patch
text/x-patch
Filename: v11-0001-Autoprewarm-global-objects-separately.patch
Type: text/x-patch
Part: 1
Message:
Re: Using read stream in autoprewarm
Patch
Format: format-patch
Series: patch v11-0001
Subject: Autoprewarm global objects separately
| File | + | − |
|---|---|---|
| contrib/pg_prewarm/autoprewarm.c | 22 | 29 |
From dbfb2fe6b9f319efd951da93ea9c1f350bac8815 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 2 Apr 2025 09:52:54 -0400
Subject: [PATCH v11 1/3] Autoprewarm global objects separately
Autoprewarm previously prewarmed global objects while prewarming blocks
from objects from the first valid database it encountered. This was
because you can't read in buffers without being connected to a database.
Prewarming global objects and objects from a single database in the
autoprewarm_database_main() function required a special case. Once we
convert autoprewarm to use a read stream, this special case will have to
be duplicated in multiple places.
Instead, modify apw_load_buffers() to prewarm the shared objects in one
invocation of autoprewarm_database_main() while connected to the first
valid database.
It is a bit fiddly but seems better than the alternative.
Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Discussion: https://postgr.es/m/CAN55FZ0TBBmrJ2vtMQ9rEk-NTL2BWQzavVp%3DiRLOUskm%2BzvNNw%40mail.gmail.com
---
contrib/pg_prewarm/autoprewarm.c | 51 ++++++++++++++------------------
1 file changed, 22 insertions(+), 29 deletions(-)
diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index 73485a2323c..172654fee25 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -347,44 +347,41 @@ apw_load_buffers(void)
apw_state->prewarm_start_idx = apw_state->prewarm_stop_idx = 0;
apw_state->prewarmed_blocks = 0;
- /* Get the info position of the first block of the next database. */
+ /*
+ * Loop through the records and launch a database worker to process
+ * objects in each database. We'll stop at the boundary of each new
+ * database and prewarm those blocks before moving to the next.
+ */
while (apw_state->prewarm_start_idx < num_elements)
{
int j = apw_state->prewarm_start_idx;
Oid current_db = blkinfo[j].database;
/*
- * Advance the prewarm_stop_idx to the first BlockInfoRecord that does
- * not belong to this database.
+ * Advance the position to the first BlockInfoRecord that does not
+ * belong to the current database.
*/
- j++;
- while (j < num_elements)
+ for (; j < num_elements; j++)
{
- if (current_db != blkinfo[j].database)
- {
- /*
- * Combine BlockInfoRecords for global objects with those of
- * the database.
- */
- if (current_db != InvalidOid)
- break;
- current_db = blkinfo[j].database;
- }
-
- j++;
+ if (blkinfo[j].database != current_db)
+ break;
}
/*
- * If we reach this point with current_db == InvalidOid, then only
- * BlockInfoRecords belonging to global objects exist. We can't
- * prewarm without a database connection, so just bail out.
+ * We can't prewarm without a database connection, so if all of the
+ * records belong to global objects, we have to bail out.
*/
- if (current_db == InvalidOid)
+ if (current_db == InvalidOid && blkinfo[j].database == InvalidOid)
break;
+ /* Connect to the first valid db to prewarm global objects. */
+ if (current_db == InvalidOid)
+ current_db = blkinfo[j].database;
+
/* Configure stop point and database for next per-database worker. */
apw_state->prewarm_stop_idx = j;
apw_state->database = current_db;
+
Assert(apw_state->prewarm_start_idx < apw_state->prewarm_stop_idx);
/* If we've run out of free buffers, don't launch another worker. */
@@ -423,8 +420,8 @@ apw_load_buffers(void)
}
/*
- * Prewarm all blocks for one database (and possibly also global objects, if
- * those got grouped with this database).
+ * Prewarm all blocks for one database or global objects (while connected to a
+ * valid database).
*/
void
autoprewarm_database_main(Datum main_arg)
@@ -462,12 +459,8 @@ autoprewarm_database_main(Datum main_arg)
CHECK_FOR_INTERRUPTS();
- /*
- * Quit if we've reached records for another database. If previous
- * blocks are of some global objects, then continue pre-warming.
- */
- if (old_blk != NULL && old_blk->database != blk->database &&
- old_blk->database != 0)
+ /* Quit if we've reached records for another database. */
+ if (old_blk != NULL && old_blk->database != blk->database)
break;
/*
--
2.34.1