From 6370184c4223a7482857a1b8f9c507c1d3c81e3c Mon Sep 17 00:00:00 2001 From: Melanie Plageman 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 Reviewed-by: Andres Freund Reviewed-by: Justin Pryzby Reviewed-by: Kyotaro Horiguchi Reviewed-by: Maciek Sakrejda Reviewed-by: Lukas Fittl 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 pg_stat_bgwriter view, archiver to reset all the counters shown in the pg_stat_archiver view, + io to reset all the counters shown in the + pg_stat_io view, wal to reset all the counters shown in the pg_stat_wal view or recovery_prefetch 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