public inbox for [email protected]
help / color / mirror / Atom feedFrom: Michael Paquier <[email protected]>
To: Postgres hackers <[email protected]>
Subject: Add callbacks for fixed-numbered stats flush in pgstats
Date: Tue, 3 Sep 2024 13:48:59 +0900
Message-ID: <[email protected]> (raw)
Hi all,
The last TODO item I had in my bucket about the generalization of
pgstats is the option to a better control on the flush of the stats
depending on the kind for fixed-numbered stats. Currently, this is
controlled by pgstat_report_stat(), that includes special handling for
WAL, IO and SLRU stats, with two generic concepts:
- Check if there are pending entries, allowing a fast-path exit.
- Do the actual flush, with a recheck on pending entries.
SLRU and IO control that with one variable each, and WAL uses a
routine for the same called pgstat_have_pending_wal(). Please find
attached a patch to generalize the concept, with two new callbacks
that can be used for fixed-numbered stats. SLRU, IO and WAL are
switched to use these (the two pgstat_flush_* routines have been kept
on purpose). This brings some clarity in the code, by making
have_iostats and have_slrustats static in their respective files. The
two pgstat_flush_* wrappers do not need a boolean as return result.
Running Postgres on scissors with a read-only workload that does not
trigger stats, I was not able to see a difference in runtime, but that
was on my own laptop, and I am planning to do more measurements on a
bigger machine.
This is in the same line of thoughts as the recent thread about the
backend init callback, generalizing more the whole facility:
https://www.postgresql.org/message-id/[email protected]
Like the other one, I wanted to send that a few days ago, but well,
life likes going its own ways sometimes.
Thanks,
--
Michael
Attachments:
[text/x-diff] 0001-Add-callbacks-to-control-flush-of-fixed-numbered-sta.patch (10.7K, ../[email protected]/2-0001-Add-callbacks-to-control-flush-of-fixed-numbered-sta.patch)
download | inline diff:
From e98f8d50c17cd8fc521bffb4bdc73ef58b7fa430 Mon Sep 17 00:00:00 2001
From: Michael Paquier <[email protected]>
Date: Tue, 3 Sep 2024 13:36:10 +0900
Subject: [PATCH] Add callbacks to control flush of fixed-numbered stats
This commit adds two callbacks in pgstats:
- have_fixed_pending_cb, to check if a stats kind has any pending stuff
waiting for a flush.
- flush_fixed_cb, to do the flush.
This is used by the SLRU, WAL and IO statistics, generalizing the
concept for all stats kinds (builtin and custom).
---
src/include/utils/pgstat_internal.h | 42 +++++++++-------
src/backend/utils/activity/pgstat.c | 63 +++++++++++++++++++-----
src/backend/utils/activity/pgstat_io.c | 22 ++++++++-
src/backend/utils/activity/pgstat_slru.c | 13 ++++-
src/backend/utils/activity/pgstat_wal.c | 19 +++++--
5 files changed, 119 insertions(+), 40 deletions(-)
diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h
index fb132e439d..d69aa05b1c 100644
--- a/src/include/utils/pgstat_internal.h
+++ b/src/include/utils/pgstat_internal.h
@@ -231,7 +231,7 @@ typedef struct PgStat_KindInfo
/*
* For variable-numbered stats: flush pending stats. Required if pending
- * data is used.
+ * data is used. See flush_fixed_cb for fixed-numbered stats.
*/
bool (*flush_pending_cb) (PgStat_EntryRef *sr, bool nowait);
@@ -259,6 +259,19 @@ typedef struct PgStat_KindInfo
*/
void (*init_shmem_cb) (void *stats);
+ /*
+ * For fixed-numbered statistics: Flush pending stats. Returns true if
+ * some of the stats could not be flushed, due to lock contention for
+ * example. Optional.
+ */
+ bool (*flush_fixed_cb) (bool nowait);
+
+ /*
+ * For fixed-numbered statistics: Check for pending stats in need of
+ * flush. Returns true if there are any stats pending for flush. Optional.
+ */
+ bool (*have_fixed_pending_cb) (void);
+
/*
* For fixed-numbered statistics: Reset All.
*/
@@ -603,7 +616,10 @@ extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
* Functions in pgstat_io.c
*/
-extern bool pgstat_flush_io(bool nowait);
+extern void pgstat_flush_io(bool nowait);
+
+extern bool pgstat_io_have_pending_cb(void);
+extern bool pgstat_io_flush_cb(bool nowait);
extern void pgstat_io_init_shmem_cb(void *stats);
extern void pgstat_io_reset_all_cb(TimestampTz ts);
extern void pgstat_io_snapshot_cb(void);
@@ -662,7 +678,8 @@ extern PgStatShared_Common *pgstat_init_entry(PgStat_Kind kind,
* Functions in pgstat_slru.c
*/
-extern bool pgstat_slru_flush(bool nowait);
+extern bool pgstat_slru_have_pending_cb(void);
+extern bool pgstat_slru_flush_cb(bool nowait);
extern void pgstat_slru_init_shmem_cb(void *stats);
extern void pgstat_slru_reset_all_cb(TimestampTz ts);
extern void pgstat_slru_snapshot_cb(void);
@@ -672,10 +689,11 @@ extern void pgstat_slru_snapshot_cb(void);
* Functions in pgstat_wal.c
*/
-extern bool pgstat_flush_wal(bool nowait);
extern void pgstat_init_wal(void);
-extern bool pgstat_have_pending_wal(void);
+extern void pgstat_flush_wal(bool nowait);
+extern bool pgstat_wal_have_pending_cb(void);
+extern bool pgstat_wal_flush_cb(bool nowait);
extern void pgstat_wal_init_shmem_cb(void *stats);
extern void pgstat_wal_reset_all_cb(TimestampTz ts);
extern void pgstat_wal_snapshot_cb(void);
@@ -705,20 +723,6 @@ extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
extern PGDLLIMPORT PgStat_LocalState pgStatLocal;
-/*
- * Variables in pgstat_io.c
- */
-
-extern PGDLLIMPORT bool have_iostats;
-
-
-/*
- * Variables in pgstat_slru.c
- */
-
-extern PGDLLIMPORT bool have_slrustats;
-
-
/*
* Implementation of inline functions declared above.
*/
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index b2ca3f39b7..8cbf706d5b 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -411,6 +411,8 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
.shared_data_off = offsetof(PgStatShared_IO, stats),
.shared_data_len = sizeof(((PgStatShared_IO *) 0)->stats),
+ .flush_fixed_cb = pgstat_io_flush_cb,
+ .have_fixed_pending_cb = pgstat_io_have_pending_cb,
.init_shmem_cb = pgstat_io_init_shmem_cb,
.reset_all_cb = pgstat_io_reset_all_cb,
.snapshot_cb = pgstat_io_snapshot_cb,
@@ -426,6 +428,8 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
.shared_data_off = offsetof(PgStatShared_SLRU, stats),
.shared_data_len = sizeof(((PgStatShared_SLRU *) 0)->stats),
+ .flush_fixed_cb = pgstat_slru_flush_cb,
+ .have_fixed_pending_cb = pgstat_slru_have_pending_cb,
.init_shmem_cb = pgstat_slru_init_shmem_cb,
.reset_all_cb = pgstat_slru_reset_all_cb,
.snapshot_cb = pgstat_slru_snapshot_cb,
@@ -441,6 +445,8 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
.shared_data_off = offsetof(PgStatShared_Wal, stats),
.shared_data_len = sizeof(((PgStatShared_Wal *) 0)->stats),
+ .flush_fixed_cb = pgstat_wal_flush_cb,
+ .have_fixed_pending_cb = pgstat_wal_have_pending_cb,
.init_shmem_cb = pgstat_wal_init_shmem_cb,
.reset_all_cb = pgstat_wal_reset_all_cb,
.snapshot_cb = pgstat_wal_snapshot_cb,
@@ -661,13 +667,37 @@ pgstat_report_stat(bool force)
}
/* Don't expend a clock check if nothing to do */
- if (dlist_is_empty(&pgStatPending) &&
- !have_iostats &&
- !have_slrustats &&
- !pgstat_have_pending_wal())
+ if (dlist_is_empty(&pgStatPending))
{
- Assert(pending_since == 0);
- return 0;
+ bool do_flush = false;
+
+ /* Check for pending fixed-numbered stats */
+ for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
+ {
+ const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
+
+ if (!kind_info)
+ continue;
+ if (!kind_info->fixed_amount)
+ {
+ Assert(kind_info->have_fixed_pending_cb == NULL);
+ continue;
+ }
+ if (!kind_info->have_fixed_pending_cb)
+ continue;
+
+ if (kind_info->have_fixed_pending_cb())
+ {
+ do_flush = true;
+ break;
+ }
+ }
+
+ if (!do_flush)
+ {
+ Assert(pending_since == 0);
+ return 0;
+ }
}
/*
@@ -720,14 +750,23 @@ pgstat_report_stat(bool force)
/* flush database / relation / function / ... stats */
partial_flush |= pgstat_flush_pending_entries(nowait);
- /* flush IO stats */
- partial_flush |= pgstat_flush_io(nowait);
+ /* flush of fixed-numbered stats */
+ for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
+ {
+ const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
- /* flush wal stats */
- partial_flush |= pgstat_flush_wal(nowait);
+ if (!kind_info)
+ continue;
+ if (!kind_info->fixed_amount)
+ {
+ Assert(kind_info->flush_fixed_cb == NULL);
+ continue;
+ }
+ if (!kind_info->flush_fixed_cb)
+ continue;
- /* flush SLRU stats */
- partial_flush |= pgstat_slru_flush(nowait);
+ partial_flush |= kind_info->flush_fixed_cb(nowait);
+ }
last_flush = now;
diff --git a/src/backend/utils/activity/pgstat_io.c b/src/backend/utils/activity/pgstat_io.c
index 8af55989ee..cc2ffc78aa 100644
--- a/src/backend/utils/activity/pgstat_io.c
+++ b/src/backend/utils/activity/pgstat_io.c
@@ -29,7 +29,7 @@ typedef struct PgStat_PendingIO
static PgStat_PendingIO PendingIOStats;
-bool have_iostats = false;
+static bool have_iostats = false;
/*
@@ -161,6 +161,24 @@ pgstat_fetch_stat_io(void)
return &pgStatLocal.snapshot.io;
}
+/*
+ * Check if there any IO stats waiting for flush.
+ */
+bool
+pgstat_io_have_pending_cb(void)
+{
+ return have_iostats;
+}
+
+/*
+ * Simpler wrapper of pgstat_io_flush_cb()
+ */
+void
+pgstat_flush_io(bool nowait)
+{
+ (void) pgstat_io_flush_cb(nowait);
+}
+
/*
* Flush out locally pending IO statistics
*
@@ -170,7 +188,7 @@ pgstat_fetch_stat_io(void)
* acquired. Otherwise, return false.
*/
bool
-pgstat_flush_io(bool nowait)
+pgstat_io_flush_cb(bool nowait)
{
LWLock *bktype_lock;
PgStat_BktypeIO *bktype_shstats;
diff --git a/src/backend/utils/activity/pgstat_slru.c b/src/backend/utils/activity/pgstat_slru.c
index 6f922a85bf..dd6f9f840e 100644
--- a/src/backend/utils/activity/pgstat_slru.c
+++ b/src/backend/utils/activity/pgstat_slru.c
@@ -32,7 +32,7 @@ static void pgstat_reset_slru_counter_internal(int index, TimestampTz ts);
* in order to avoid memory allocation.
*/
static PgStat_SLRUStats pending_SLRUStats[SLRU_NUM_ELEMENTS];
-bool have_slrustats = false;
+static bool have_slrustats = false;
/*
@@ -143,6 +143,15 @@ pgstat_get_slru_index(const char *name)
return (SLRU_NUM_ELEMENTS - 1);
}
+/*
+ * Check if there are any SLRU stats entries waiting for flush.
+ */
+bool
+pgstat_slru_have_pending_cb(void)
+{
+ return have_slrustats;
+}
+
/*
* Flush out locally pending SLRU stats entries
*
@@ -153,7 +162,7 @@ pgstat_get_slru_index(const char *name)
* acquired. Otherwise return false.
*/
bool
-pgstat_slru_flush(bool nowait)
+pgstat_slru_flush_cb(bool nowait)
{
PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
int i;
diff --git a/src/backend/utils/activity/pgstat_wal.c b/src/backend/utils/activity/pgstat_wal.c
index e2a3f6b865..3d76091f71 100644
--- a/src/backend/utils/activity/pgstat_wal.c
+++ b/src/backend/utils/activity/pgstat_wal.c
@@ -71,6 +71,15 @@ pgstat_fetch_stat_wal(void)
return &pgStatLocal.snapshot.wal;
}
+/*
+ * Simple wrapper of pgstat_wal_flush_cb()
+ */
+void
+pgstat_flush_wal(bool nowait)
+{
+ (void) pgstat_wal_flush_cb(nowait);
+}
+
/*
* Calculate how much WAL usage counters have increased by subtracting the
* previous counters from the current ones.
@@ -79,7 +88,7 @@ pgstat_fetch_stat_wal(void)
* acquired. Otherwise return false.
*/
bool
-pgstat_flush_wal(bool nowait)
+pgstat_wal_flush_cb(bool nowait)
{
PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
WalUsage wal_usage_diff = {0};
@@ -92,7 +101,7 @@ pgstat_flush_wal(bool nowait)
* This function can be called even if nothing at all has happened. Avoid
* taking lock for nothing in that case.
*/
- if (!pgstat_have_pending_wal())
+ if (!pgstat_wal_have_pending_cb())
return false;
/*
@@ -141,8 +150,8 @@ void
pgstat_init_wal(void)
{
/*
- * Initialize prevWalUsage with pgWalUsage so that pgstat_flush_wal() can
- * calculate how much pgWalUsage counters are increased by subtracting
+ * Initialize prevWalUsage with pgWalUsage so that pgstat_wal_flush_cb()
+ * can calculate how much pgWalUsage counters are increased by subtracting
* prevWalUsage from pgWalUsage.
*/
prevWalUsage = pgWalUsage;
@@ -156,7 +165,7 @@ pgstat_init_wal(void)
* data pages.
*/
bool
-pgstat_have_pending_wal(void)
+pgstat_wal_have_pending_cb(void)
{
return pgWalUsage.wal_records != prevWalUsage.wal_records ||
PendingWalStats.wal_write != 0 ||
--
2.45.2
[application/pgp-signature] signature.asc (833B, ../[email protected]/3-signature.asc)
download
view thread (7+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected]
Subject: Re: Add callbacks for fixed-numbered stats flush in pgstats
In-Reply-To: <[email protected]>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox