]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Add new pgstats routine to split pending data setup
authorMichael Paquier <michael@paquier.xyz>
Tue, 21 Jul 2026 23:15:00 +0000 (08:15 +0900)
committerMichael Paquier <michael@paquier.xyz>
Tue, 21 Jul 2026 23:15:00 +0000 (08:15 +0900)
This commit adds pgstat_prep_pending_from_entry_ref(), a new pgstats
routine that is able to prepare an existing PgStat_EntryRef to receive
pending stats.  This split gives a way for callers to obtain first a
reference via pgstat_get_entry_ref(), then set up pending data as two
separate, distinctive, steps.

Previously, the only way to get an entry reference with pending data
ready was pgstat_prep_pending_entry(), which bundles lookup, creation,
and pending setup in a single call.  Callers that need finer control
over the entry creation had no way to attach pending data to an
already-obtained entry reference.  One case where this has shown to
matter for a stats kind is where one wants to check some capacity (for
example where a GUC bounds the maximum numer of entries allowed) before
deciding if a new entry should be created.  So this split can help in
reducing calls to pgstat_get_entry_ref(), meaning less shmem hash table
lookups.

The only logical ordering change is that pgStatPendingContext is
initialized after calling pgstat_get_entry_ref() in
pgstat_prep_pending_entry().  This does not matter in practice.

pgstat_prep_pending_entry() is refactored to use the new function
internally.  All the existing callers are unchanged.  Existing
out-of-core custom stats kinds should see no impact.

Author: Sami Imseih <samimseih@gmail.com>
Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CAA5RZ0sV+TsLejUMhAM=PJoOm8u-t8ru7B67KvyLCy=19sM87g@mail.gmail.com

src/backend/utils/activity/pgstat.c
src/include/utils/pgstat_internal.h

index 9234854b8b5e13e73c5fc14dacb79954f8011f91..50cd07822b4ac7e5a7127bce38687e71f9937615 100644 (file)
@@ -1311,29 +1311,10 @@ pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid, uint64 objid, bool *creat
 {
        PgStat_EntryRef *entry_ref;
 
-       /* need to be able to flush out */
-       Assert(pgstat_get_kind_info(kind)->flush_pending_cb != NULL);
-
-       if (unlikely(!pgStatPendingContext))
-       {
-               pgStatPendingContext =
-                       AllocSetContextCreate(TopMemoryContext,
-                                                                 "PgStat Pending",
-                                                                 ALLOCSET_SMALL_SIZES);
-       }
-
        entry_ref = pgstat_get_entry_ref(kind, dboid, objid,
                                                                         true, created_entry);
 
-       if (entry_ref->pending == NULL)
-       {
-               size_t          entrysize = pgstat_get_kind_info(kind)->pending_size;
-
-               Assert(entrysize != (size_t) -1);
-
-               entry_ref->pending = MemoryContextAllocZero(pgStatPendingContext, entrysize);
-               dlist_push_tail(&pgStatPending, &entry_ref->pending_node);
-       }
+       pgstat_prep_pending_from_entry_ref(entry_ref);
 
        return entry_ref;
 }
@@ -1377,6 +1358,40 @@ pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref)
        dlist_delete(&entry_ref->pending_node);
 }
 
+/*
+ * Prepare the given entry to receive pending stats, if not already done.
+ */
+void
+pgstat_prep_pending_from_entry_ref(PgStat_EntryRef *entry_ref)
+{
+       PgStat_Kind kind;
+
+       Assert(entry_ref != NULL);
+
+       kind = entry_ref->shared_entry->key.kind;
+
+       /* need to be able to flush out */
+       Assert(pgstat_get_kind_info(kind)->flush_pending_cb != NULL);
+
+       if (entry_ref->pending == NULL)
+       {
+               size_t          entrysize = pgstat_get_kind_info(kind)->pending_size;
+
+               Assert(entrysize != (size_t) -1);
+
+               if (unlikely(!pgStatPendingContext))
+               {
+                       pgStatPendingContext =
+                               AllocSetContextCreate(TopMemoryContext,
+                                                                         "PgStat Pending",
+                                                                         ALLOCSET_SMALL_SIZES);
+               }
+
+               entry_ref->pending = MemoryContextAllocZero(pgStatPendingContext, entrysize);
+               dlist_push_tail(&pgStatPending, &entry_ref->pending_node);
+       }
+}
+
 /*
  * Flush out pending variable-numbered stats.
  */
index e62122b883b6f4967b107cd9170700435e649d7a..b0a1769196677ca108f15e20907e821782814ae3 100644 (file)
@@ -680,6 +680,7 @@ extern void pgstat_assert_is_up(void);
 #endif
 
 extern void pgstat_delete_pending_entry(PgStat_EntryRef *entry_ref);
+extern void pgstat_prep_pending_from_entry_ref(PgStat_EntryRef *entry_ref);
 extern PgStat_EntryRef *pgstat_prep_pending_entry(PgStat_Kind kind, Oid dboid,
                                                                                                  uint64 objid,
                                                                                                  bool *created_entry);