v40-0003-Aggregate-IO-operation-stats-per-BackendType.patch
application/octet-stream
Filename: v40-0003-Aggregate-IO-operation-stats-per-BackendType.patch
Type: application/octet-stream
Part: 1
Patch
Format: format-patch
Series: patch v40-0003
Subject: Aggregate IO operation stats per BackendType
| File | + | − |
|---|---|---|
| doc/src/sgml/monitoring.sgml | 2 | 0 |
| src/backend/utils/activity/pgstat_bgwriter.c | 6 | 1 |
| src/backend/utils/activity/pgstat.c | 35 | 0 |
| src/backend/utils/activity/pgstat_checkpointer.c | 6 | 1 |
| src/backend/utils/activity/pgstat_io_ops.c | 207 | 0 |
| src/backend/utils/activity/pgstat_relation.c | 13 | 2 |
| src/backend/utils/activity/pgstat_shmem.c | 4 | 0 |
| src/backend/utils/activity/pgstat_wal.c | 3 | 1 |
| src/backend/utils/adt/pgstatfuncs.c | 3 | 1 |
| src/include/miscadmin.h | 2 | 0 |
| src/include/pgstat.h | 8 | 0 |
| src/include/utils/pgstat_internal.h | 46 | 0 |
| src/tools/pgindent/typedefs.list | 4 | 0 |
From 6370184c4223a7482857a1b8f9c507c1d3c81e3c Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Mon, 5 Dec 2022 19:38:07 -0500
Subject: [PATCH v40 3/4] Aggregate IO operation stats per BackendType
Stats on IOOps on all IOObjects in all IOContexts for a backend are
already tracked locally. Add functionality for backends to flush these
stats to shared memory and accumulate them with those from all other
backends, exited and live. Also add reset and snapshot functions used by
cumulative stats system for management of these statistics.
The aggregated stats in shared memory could be extended in the future
with per-backend stats -- useful for per connection IO statistics and
monitoring.
Some BackendTypes will not flush their pending statistics at regular
intervals and explicitly call pgstat_flush_io_ops() during the course of
normal operations to flush their backend-local IO operation statistics
to shared memory in a timely manner.
Because not all BackendType, IOOp, IOObject, IOContext combinations are
valid, the validity of the stats is checked before flushing pending
stats and before reading in the existing stats file to shared memory.
Author: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Reviewed-by: Justin Pryzby <pryzby@telsasoft.com>
Reviewed-by: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Reviewed-by: Maciek Sakrejda <m.sakrejda@gmail.com>
Reviewed-by: Lukas Fittl <lukas@fittl.com>
Discussion: https://www.postgresql.org/message-id/flat/20200124195226.lth52iydq2n2uilq%40alap3.anarazel.de
---
doc/src/sgml/monitoring.sgml | 2 +
src/backend/utils/activity/pgstat.c | 35 +++
src/backend/utils/activity/pgstat_bgwriter.c | 7 +-
.../utils/activity/pgstat_checkpointer.c | 7 +-
src/backend/utils/activity/pgstat_io_ops.c | 207 ++++++++++++++++++
src/backend/utils/activity/pgstat_relation.c | 15 +-
src/backend/utils/activity/pgstat_shmem.c | 4 +
src/backend/utils/activity/pgstat_wal.c | 4 +-
src/backend/utils/adt/pgstatfuncs.c | 4 +-
src/include/miscadmin.h | 2 +
src/include/pgstat.h | 8 +
src/include/utils/pgstat_internal.h | 46 ++++
src/tools/pgindent/typedefs.list | 4 +
13 files changed, 339 insertions(+), 6 deletions(-)
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 11a8ebe5ec..e0db24c154 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -5396,6 +5396,8 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
the <structname>pg_stat_bgwriter</structname>
view, <literal>archiver</literal> to reset all the counters shown in
the <structname>pg_stat_archiver</structname> view,
+ <literal>io</literal> to reset all the counters shown in the
+ <structname>pg_stat_io</structname> view,
<literal>wal</literal> to reset all the counters shown in the
<structname>pg_stat_wal</structname> view or
<literal>recovery_prefetch</literal> to reset all the counters shown
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index 1ebe3bbf29..d2ba5fd9f3 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -359,6 +359,15 @@ static const PgStat_KindInfo pgstat_kind_infos[PGSTAT_NUM_KINDS] = {
.snapshot_cb = pgstat_checkpointer_snapshot_cb,
},
+ [PGSTAT_KIND_IOOPS] = {
+ .name = "io_ops",
+
+ .fixed_amount = true,
+
+ .reset_all_cb = pgstat_io_ops_reset_all_cb,
+ .snapshot_cb = pgstat_io_ops_snapshot_cb,
+ },
+
[PGSTAT_KIND_SLRU] = {
.name = "slru",
@@ -582,6 +591,7 @@ pgstat_report_stat(bool force)
/* Don't expend a clock check if nothing to do */
if (dlist_is_empty(&pgStatPending) &&
+ !have_ioopstats &&
!have_slrustats &&
!pgstat_have_pending_wal())
{
@@ -628,6 +638,9 @@ pgstat_report_stat(bool force)
/* flush database / relation / function / ... stats */
partial_flush |= pgstat_flush_pending_entries(nowait);
+ /* flush IO Operations stats */
+ partial_flush |= pgstat_flush_io_ops(nowait);
+
/* flush wal stats */
partial_flush |= pgstat_flush_wal(nowait);
@@ -1321,6 +1334,14 @@ pgstat_write_statsfile(void)
pgstat_build_snapshot_fixed(PGSTAT_KIND_CHECKPOINTER);
write_chunk_s(fpout, &pgStatLocal.snapshot.checkpointer);
+ /*
+ * Write IO Operations stats struct
+ */
+ pgstat_build_snapshot_fixed(PGSTAT_KIND_IOOPS);
+ write_chunk_s(fpout, &pgStatLocal.snapshot.io_ops.stat_reset_timestamp);
+ for (int bktype = 0; bktype < BACKEND_NUM_TYPES; bktype++)
+ write_chunk_s(fpout, &pgStatLocal.snapshot.io_ops.stats[bktype]);
+
/*
* Write SLRU stats struct
*/
@@ -1495,6 +1516,20 @@ pgstat_read_statsfile(void)
if (!read_chunk_s(fpin, &shmem->checkpointer.stats))
goto error;
+ /*
+ * Read IO Operations stats struct
+ */
+ if (!read_chunk_s(fpin, &shmem->io_ops.stat_reset_timestamp))
+ goto error;
+
+ for (int bktype = 0; bktype < BACKEND_NUM_TYPES; bktype++)
+ {
+ pgstat_backend_io_stats_assert_well_formed(&shmem->io_ops.stats[bktype],
+ (BackendType) bktype);
+ if (!read_chunk_s(fpin, &shmem->io_ops.stats[bktype].data))
+ goto error;
+ }
+
/*
* Read SLRU stats struct
*/
diff --git a/src/backend/utils/activity/pgstat_bgwriter.c b/src/backend/utils/activity/pgstat_bgwriter.c
index fbb1edc527..3d7f90a1b7 100644
--- a/src/backend/utils/activity/pgstat_bgwriter.c
+++ b/src/backend/utils/activity/pgstat_bgwriter.c
@@ -24,7 +24,7 @@ PgStat_BgWriterStats PendingBgWriterStats = {0};
/*
- * Report bgwriter statistics
+ * Report bgwriter and IO Operation statistics
*/
void
pgstat_report_bgwriter(void)
@@ -56,6 +56,11 @@ pgstat_report_bgwriter(void)
* Clear out the statistics buffer, so it can be re-used.
*/
MemSet(&PendingBgWriterStats, 0, sizeof(PendingBgWriterStats));
+
+ /*
+ * Report IO Operations statistics
+ */
+ pgstat_flush_io_ops(false);
}
/*
diff --git a/src/backend/utils/activity/pgstat_checkpointer.c b/src/backend/utils/activity/pgstat_checkpointer.c
index af8d513e7b..cfcf127210 100644
--- a/src/backend/utils/activity/pgstat_checkpointer.c
+++ b/src/backend/utils/activity/pgstat_checkpointer.c
@@ -24,7 +24,7 @@ PgStat_CheckpointerStats PendingCheckpointerStats = {0};
/*
- * Report checkpointer statistics
+ * Report checkpointer and IO Operation statistics
*/
void
pgstat_report_checkpointer(void)
@@ -62,6 +62,11 @@ pgstat_report_checkpointer(void)
* Clear out the statistics buffer, so it can be re-used.
*/
MemSet(&PendingCheckpointerStats, 0, sizeof(PendingCheckpointerStats));
+
+ /*
+ * Report IO Operation statistics
+ */
+ pgstat_flush_io_ops(false);
}
/*
diff --git a/src/backend/utils/activity/pgstat_io_ops.c b/src/backend/utils/activity/pgstat_io_ops.c
index 6fbb6b185e..66c8e3d035 100644
--- a/src/backend/utils/activity/pgstat_io_ops.c
+++ b/src/backend/utils/activity/pgstat_io_ops.c
@@ -20,6 +20,42 @@
#include "utils/pgstat_internal.h"
static PgStat_IOContextOps pending_IOOpStats;
+bool have_ioopstats = false;
+
+
+/*
+ * Helper function to accumulate source PgStat_IOOpCounters into target
+ * PgStat_IOOpCounters. If either of the passed-in PgStat_IOOpCounters are
+ * members of PgStatShared_IOContextOps, the caller is responsible for ensuring
+ * that the appropriate lock is held.
+ */
+static void
+pgstat_accum_io_op(PgStat_IOOpCounters *target, PgStat_IOOpCounters *source, IOOp io_op)
+{
+ switch (io_op)
+ {
+ case IOOP_EVICT:
+ target->evictions += source->evictions;
+ return;
+ case IOOP_EXTEND:
+ target->extends += source->extends;
+ return;
+ case IOOP_FSYNC:
+ target->fsyncs += source->fsyncs;
+ return;
+ case IOOP_READ:
+ target->reads += source->reads;
+ return;
+ case IOOP_REUSE:
+ target->reuses += source->reuses;
+ return;
+ case IOOP_WRITE:
+ target->writes += source->writes;
+ return;
+ }
+
+ elog(ERROR, "unrecognized IOOp value: %d", io_op);
+}
void
pgstat_count_io_op(IOOp io_op, IOObject io_object, IOContext io_context)
@@ -53,6 +89,88 @@ pgstat_count_io_op(IOOp io_op, IOObject io_object, IOContext io_context)
pending_counters->writes++;
break;
}
+
+ have_ioopstats = true;
+}
+
+PgStat_BackendIOContextOps *
+pgstat_fetch_backend_io_context_ops(void)
+{
+ pgstat_snapshot_fixed(PGSTAT_KIND_IOOPS);
+
+ return &pgStatLocal.snapshot.io_ops;
+}
+
+/*
+ * Flush out locally pending IO Operation statistics entries
+ *
+ * If no stats have been recorded, this function returns false.
+ *
+ * If nowait is true, this function returns true if the lock could not be
+ * acquired. Otherwise, return false.
+ */
+bool
+pgstat_flush_io_ops(bool nowait)
+{
+ PgStatShared_IOContextOps *type_shstats;
+ bool expect_backend_stats = true;
+
+ if (!have_ioopstats)
+ return false;
+
+ type_shstats =
+ &pgStatLocal.shmem->io_ops.stats[MyBackendType];
+
+ if (!nowait)
+ LWLockAcquire(&type_shstats->lock, LW_EXCLUSIVE);
+ else if (!LWLockConditionalAcquire(&type_shstats->lock, LW_EXCLUSIVE))
+ return true;
+
+ expect_backend_stats = pgstat_io_op_stats_collected(MyBackendType);
+
+ for (IOContext io_context = IOCONTEXT_BULKREAD;
+ io_context < IOCONTEXT_NUM_TYPES; io_context++)
+ {
+ PgStatShared_IOObjectOps *shared_objs = &type_shstats->data[io_context];
+ PgStat_IOObjectOps *pending_objs = &pending_IOOpStats.data[io_context];
+
+ for (IOObject io_object = IOOBJECT_RELATION;
+ io_object < IOOBJECT_NUM_TYPES; io_object++)
+ {
+ PgStat_IOOpCounters *sharedent = &shared_objs->data[io_object];
+ PgStat_IOOpCounters *pendingent = &pending_objs->data[io_object];
+
+ if (!expect_backend_stats ||
+ !pgstat_bktype_io_context_io_object_valid(MyBackendType,
+ io_context, io_object))
+ {
+ pgstat_io_context_ops_assert_zero(sharedent);
+ pgstat_io_context_ops_assert_zero(pendingent);
+ continue;
+ }
+
+ for (IOOp io_op = IOOP_EVICT; io_op < IOOP_NUM_TYPES; io_op++)
+ {
+ if (!pgstat_io_op_valid(MyBackendType, io_context, io_object,
+ io_op))
+ {
+ pgstat_io_op_assert_zero(sharedent, io_op);
+ pgstat_io_op_assert_zero(pendingent, io_op);
+ continue;
+ }
+
+ pgstat_accum_io_op(sharedent, pendingent, io_op);
+ }
+ }
+ }
+
+ LWLockRelease(&type_shstats->lock);
+
+ memset(&pending_IOOpStats, 0, sizeof(pending_IOOpStats));
+
+ have_ioopstats = false;
+
+ return false;
}
const char *
@@ -115,6 +233,55 @@ pgstat_io_op_desc(IOOp io_op)
pg_unreachable();
}
+void
+pgstat_io_ops_reset_all_cb(TimestampTz ts)
+{
+ PgStatShared_BackendIOContextOps *backends_stats_shmem = &pgStatLocal.shmem->io_ops;
+
+ for (int i = 0; i < BACKEND_NUM_TYPES; i++)
+ {
+ PgStatShared_IOContextOps *stats_shmem = &backends_stats_shmem->stats[i];
+
+ LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
+
+ /*
+ * Use the lock in the first BackendType's PgStat_IOContextOps to
+ * protect the reset timestamp as well.
+ */
+ if (i == 0)
+ backends_stats_shmem->stat_reset_timestamp = ts;
+
+ memset(stats_shmem->data, 0, sizeof(stats_shmem->data));
+ LWLockRelease(&stats_shmem->lock);
+ }
+}
+
+void
+pgstat_io_ops_snapshot_cb(void)
+{
+ PgStatShared_BackendIOContextOps *backends_stats_shmem = &pgStatLocal.shmem->io_ops;
+ PgStat_BackendIOContextOps *backends_stats_snap = &pgStatLocal.snapshot.io_ops;
+
+ for (int i = 0; i < BACKEND_NUM_TYPES; i++)
+ {
+ PgStatShared_IOContextOps *stats_shmem = &backends_stats_shmem->stats[i];
+ PgStat_IOContextOps *stats_snap = &backends_stats_snap->stats[i];
+
+ LWLockAcquire(&stats_shmem->lock, LW_SHARED);
+
+ /*
+ * Use the lock in the first BackendType's PgStat_IOContextOps to
+ * protect the reset timestamp as well.
+ */
+ if (i == 0)
+ backends_stats_snap->stat_reset_timestamp =
+ backends_stats_shmem->stat_reset_timestamp;
+
+ memcpy(stats_snap->data, stats_shmem->data, sizeof(stats_shmem->data));
+ LWLockRelease(&stats_shmem->lock);
+ }
+}
+
/*
* IO Operation statistics are not collected for all BackendTypes.
*
@@ -278,3 +445,43 @@ pgstat_expect_io_op(BackendType bktype, IOContext io_context, IOObject io_object
return true;
}
+
+/*
+ * Assert that stats have not been counted for any combination of IOContext,
+ * IOObject, and IOOp which is not valid for the passed-in BackendType. The
+ * passed-in array of PgStat_IOOpCounters must contain stats from the
+ * BackendType specified by the second parameter. Caller is responsible for
+ * locking of the passed-in PgStatShared_IOContextOps, if needed.
+ */
+void
+pgstat_backend_io_stats_assert_well_formed(PgStatShared_IOContextOps *backend_io_context_ops,
+ BackendType bktype)
+{
+ bool expect_backend_stats = pgstat_io_op_stats_collected(bktype);
+
+ for (IOContext io_context = IOCONTEXT_BULKREAD;
+ io_context < IOCONTEXT_NUM_TYPES; io_context++)
+ {
+ PgStatShared_IOObjectOps *context = &backend_io_context_ops->data[io_context];
+
+ for (IOObject io_object = IOOBJECT_RELATION;
+ io_object < IOOBJECT_NUM_TYPES; io_object++)
+ {
+ PgStat_IOOpCounters *object = &context->data[io_object];
+
+ if (!expect_backend_stats ||
+ !pgstat_bktype_io_context_io_object_valid(bktype, io_context,
+ io_object))
+ {
+ pgstat_io_context_ops_assert_zero(object);
+ continue;
+ }
+
+ for (IOOp io_op = IOOP_EVICT; io_op < IOOP_NUM_TYPES; io_op++)
+ {
+ if (!pgstat_io_op_valid(bktype, io_context, io_object, io_op))
+ pgstat_io_op_assert_zero(object, io_op);
+ }
+ }
+ }
+}
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index f92e16e7af..1c84e1a5f0 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -206,7 +206,7 @@ pgstat_drop_relation(Relation rel)
}
/*
- * Report that the table was just vacuumed.
+ * Report that the table was just vacuumed and flush IO Operation statistics.
*/
void
pgstat_report_vacuum(Oid tableoid, bool shared,
@@ -258,10 +258,18 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
}
pgstat_unlock_entry(entry_ref);
+
+ /*
+ * Flush IO Operations statistics now. pgstat_report_stat() will flush IO
+ * Operation stats, however this will not be called until after an entire
+ * autovacuum cycle is done -- which will likely vacuum many relations --
+ * or until the VACUUM command has processed all tables and committed.
+ */
+ pgstat_flush_io_ops(false);
}
/*
- * Report that the table was just analyzed.
+ * Report that the table was just analyzed and flush IO Operation statistics.
*
* Caller must provide new live- and dead-tuples estimates, as well as a
* flag indicating whether to reset the changes_since_analyze counter.
@@ -341,6 +349,9 @@ pgstat_report_analyze(Relation rel,
}
pgstat_unlock_entry(entry_ref);
+
+ /* see pgstat_report_vacuum() */
+ pgstat_flush_io_ops(false);
}
/*
diff --git a/src/backend/utils/activity/pgstat_shmem.c b/src/backend/utils/activity/pgstat_shmem.c
index 706692862c..4251079ae1 100644
--- a/src/backend/utils/activity/pgstat_shmem.c
+++ b/src/backend/utils/activity/pgstat_shmem.c
@@ -202,6 +202,10 @@ StatsShmemInit(void)
LWLockInitialize(&ctl->checkpointer.lock, LWTRANCHE_PGSTATS_DATA);
LWLockInitialize(&ctl->slru.lock, LWTRANCHE_PGSTATS_DATA);
LWLockInitialize(&ctl->wal.lock, LWTRANCHE_PGSTATS_DATA);
+
+ for (int i = 0; i < BACKEND_NUM_TYPES; i++)
+ LWLockInitialize(&ctl->io_ops.stats[i].lock,
+ LWTRANCHE_PGSTATS_DATA);
}
else
{
diff --git a/src/backend/utils/activity/pgstat_wal.c b/src/backend/utils/activity/pgstat_wal.c
index 5a878bd115..9cac407b42 100644
--- a/src/backend/utils/activity/pgstat_wal.c
+++ b/src/backend/utils/activity/pgstat_wal.c
@@ -34,7 +34,7 @@ static WalUsage prevWalUsage;
/*
* Calculate how much WAL usage counters have increased and update
- * shared statistics.
+ * shared WAL and IO Operation statistics.
*
* Must be called by processes that generate WAL, that do not call
* pgstat_report_stat(), like walwriter.
@@ -43,6 +43,8 @@ void
pgstat_report_wal(bool force)
{
pgstat_flush_wal(force);
+
+ pgstat_flush_io_ops(force);
}
/*
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index ae3365d917..a135cad0ce 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -2090,6 +2090,8 @@ pg_stat_reset_shared(PG_FUNCTION_ARGS)
pgstat_reset_of_kind(PGSTAT_KIND_BGWRITER);
pgstat_reset_of_kind(PGSTAT_KIND_CHECKPOINTER);
}
+ else if (strcmp(target, "io") == 0)
+ pgstat_reset_of_kind(PGSTAT_KIND_IOOPS);
else if (strcmp(target, "recovery_prefetch") == 0)
XLogPrefetchResetStats();
else if (strcmp(target, "wal") == 0)
@@ -2098,7 +2100,7 @@ pg_stat_reset_shared(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unrecognized reset target: \"%s\"", target),
- errhint("Target must be \"archiver\", \"bgwriter\", \"recovery_prefetch\", or \"wal\".")));
+ errhint("Target must be \"archiver\", \"io\", \"bgwriter\", \"recovery_prefetch\", or \"wal\".")));
PG_RETURN_VOID();
}
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 795182fa51..aa14338221 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -331,6 +331,8 @@ typedef enum BackendType
B_WAL_WRITER,
} BackendType;
+#define BACKEND_NUM_TYPES (B_WAL_WRITER + 1)
+
extern PGDLLIMPORT BackendType MyBackendType;
extern const char *GetBackendTypeDesc(BackendType backendType);
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index a57e39042f..357973ee8c 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -48,6 +48,7 @@ typedef enum PgStat_Kind
PGSTAT_KIND_ARCHIVER,
PGSTAT_KIND_BGWRITER,
PGSTAT_KIND_CHECKPOINTER,
+ PGSTAT_KIND_IOOPS,
PGSTAT_KIND_SLRU,
PGSTAT_KIND_WAL,
} PgStat_Kind;
@@ -333,6 +334,12 @@ typedef struct PgStat_IOContextOps
PgStat_IOObjectOps data[IOCONTEXT_NUM_TYPES];
} PgStat_IOContextOps;
+typedef struct PgStat_BackendIOContextOps
+{
+ TimestampTz stat_reset_timestamp;
+ PgStat_IOContextOps stats[BACKEND_NUM_TYPES];
+} PgStat_BackendIOContextOps;
+
typedef struct PgStat_StatDBEntry
{
PgStat_Counter n_xact_commit;
@@ -515,6 +522,7 @@ extern PgStat_CheckpointerStats *pgstat_fetch_stat_checkpointer(void);
*/
extern void pgstat_count_io_op(IOOp io_op, IOObject io_object, IOContext io_context);
+extern PgStat_BackendIOContextOps *pgstat_fetch_backend_io_context_ops(void);
extern const char *pgstat_io_context_desc(IOContext io_context);
extern const char *pgstat_io_object_desc(IOObject io_object);
extern const char *pgstat_io_op_desc(IOOp io_op);
diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h
index e2c7b59324..923e324011 100644
--- a/src/include/utils/pgstat_internal.h
+++ b/src/include/utils/pgstat_internal.h
@@ -329,6 +329,31 @@ typedef struct PgStatShared_Checkpointer
PgStat_CheckpointerStats reset_offset;
} PgStatShared_Checkpointer;
+
+typedef struct PgStatShared_IOObjectOps
+{
+ PgStat_IOOpCounters data[IOOBJECT_NUM_TYPES];
+} PgStatShared_IOObjectOps;
+
+typedef struct PgStatShared_IOContextOps
+{
+ /*
+ * lock protects ->data If this PgStatShared_IOContextOps is
+ * PgStatShared_BackendIOContextOps->stats[0], lock also protects
+ * PgStatShared_BackendIOContextOps->stat_reset_timestamp.
+ */
+ LWLock lock;
+ PgStatShared_IOObjectOps data[IOCONTEXT_NUM_TYPES];
+} PgStatShared_IOContextOps;
+
+typedef struct PgStatShared_BackendIOContextOps
+{
+ /* ->stats_reset_timestamp is protected by ->stats[0].lock */
+ TimestampTz stat_reset_timestamp;
+ PgStatShared_IOContextOps stats[BACKEND_NUM_TYPES];
+} PgStatShared_BackendIOContextOps;
+
+
typedef struct PgStatShared_SLRU
{
/* lock protects ->stats */
@@ -419,6 +444,7 @@ typedef struct PgStat_ShmemControl
PgStatShared_Archiver archiver;
PgStatShared_BgWriter bgwriter;
PgStatShared_Checkpointer checkpointer;
+ PgStatShared_BackendIOContextOps io_ops;
PgStatShared_SLRU slru;
PgStatShared_Wal wal;
} PgStat_ShmemControl;
@@ -442,6 +468,8 @@ typedef struct PgStat_Snapshot
PgStat_CheckpointerStats checkpointer;
+ PgStat_BackendIOContextOps io_ops;
+
PgStat_SLRUStats slru[SLRU_NUM_ELEMENTS];
PgStat_WalStats wal;
@@ -549,6 +577,19 @@ extern void pgstat_database_reset_timestamp_cb(PgStatShared_Common *header, Time
extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
+/*
+ * Functions in pgstat_io_ops.c
+ */
+
+extern void pgstat_io_ops_reset_all_cb(TimestampTz ts);
+extern void pgstat_io_ops_snapshot_cb(void);
+extern bool pgstat_flush_io_ops(bool nowait);
+extern void pgstat_backend_io_stats_assert_well_formed(
+ PgStatShared_IOContextOps *backend_io_context_ops,
+ BackendType bktype);
+
+
+
/*
* Functions in pgstat_relation.c
*/
@@ -641,6 +682,11 @@ extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
extern PGDLLIMPORT PgStat_LocalState pgStatLocal;
+/*
+ * Variables in pgstat_io_ops.c
+ */
+
+extern PGDLLIMPORT bool have_ioopstats;
/*
* Variables in pgstat_slru.c
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 28362f00a4..2214e8e713 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -2005,12 +2005,15 @@ PgFdwRelationInfo
PgFdwScanState
PgIfAddrCallback
PgStatShared_Archiver
+PgStatShared_BackendIOContextOps
PgStatShared_BgWriter
PgStatShared_Checkpointer
PgStatShared_Common
PgStatShared_Database
PgStatShared_Function
PgStatShared_HashEntry
+PgStatShared_IOContextOps
+PgStatShared_IOObjectOps
PgStatShared_Relation
PgStatShared_ReplSlot
PgStatShared_SLRU
@@ -2018,6 +2021,7 @@ PgStatShared_Subscription
PgStatShared_Wal
PgStat_ArchiverStats
PgStat_BackendFunctionEntry
+PgStat_BackendIOContextOps
PgStat_BackendSubEntry
PgStat_BgWriterStats
PgStat_CheckpointerStats
--
2.38.1