1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Refactor some code related to backend statistics

This commit changes the way pending backend statistics are tracked by
moving them into a new structure called PgStat_BackendPending, removing
PgStat_BackendPendingIO.  PgStat_BackendPending currently only includes
PgStat_PendingIO for the pending I/O stats.

pgstat_flush_backend() is extended with a "flags" argument to control
which parts of the stats of a backend should be flushed.

With this refactoring, it becomes easier to plug into backend statistics
more data.  A patch to add information related to WAL in this stats kind
is under discussion.

Author: Bertrand Drouvot
Discussion: https://postgr.es/m/Z3zqc4o09dM/Ezyz@ip-10-97-1-34.eu-west-3.compute.internal
This commit is contained in:
Michael Paquier
2025-01-10 09:00:48 +09:00
parent 39e3bcae44
commit 2c14037bb5
8 changed files with 76 additions and 35 deletions

View File

@ -370,7 +370,7 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
.shared_size = sizeof(PgStatShared_Backend), .shared_size = sizeof(PgStatShared_Backend),
.shared_data_off = offsetof(PgStatShared_Backend, stats), .shared_data_off = offsetof(PgStatShared_Backend, stats),
.shared_data_len = sizeof(((PgStatShared_Backend *) 0)->stats), .shared_data_len = sizeof(((PgStatShared_Backend *) 0)->stats),
.pending_size = sizeof(PgStat_BackendPendingIO), .pending_size = sizeof(PgStat_BackendPending),
.flush_pending_cb = pgstat_backend_flush_cb, .flush_pending_cb = pgstat_backend_flush_cb,
.reset_timestamp_cb = pgstat_backend_reset_timestamp_cb, .reset_timestamp_cb = pgstat_backend_reset_timestamp_cb,

View File

@ -39,23 +39,21 @@ pgstat_fetch_stat_backend(ProcNumber procNumber)
} }
/* /*
* Flush out locally pending backend statistics * Flush out locally pending backend IO statistics. Locking is managed
* * by the caller.
* If no stats have been recorded, this function returns false.
*/ */
bool static void
pgstat_backend_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) pgstat_flush_backend_entry_io(PgStat_EntryRef *entry_ref)
{ {
PgStatShared_Backend *shbackendioent; PgStatShared_Backend *shbackendent;
PgStat_BackendPendingIO *pendingent; PgStat_BackendPending *pendingent;
PgStat_BktypeIO *bktype_shstats; PgStat_BktypeIO *bktype_shstats;
PgStat_PendingIO *pending_io;
if (!pgstat_lock_entry(entry_ref, nowait)) shbackendent = (PgStatShared_Backend *) entry_ref->shared_stats;
return false; pendingent = (PgStat_BackendPending *) entry_ref->pending;
bktype_shstats = &shbackendent->stats.io_stats;
shbackendioent = (PgStatShared_Backend *) entry_ref->shared_stats; pending_io = &pendingent->pending_io;
bktype_shstats = &shbackendioent->stats.stats;
pendingent = (PgStat_BackendPendingIO *) entry_ref->pending;
for (int io_object = 0; io_object < IOOBJECT_NUM_TYPES; io_object++) for (int io_object = 0; io_object < IOOBJECT_NUM_TYPES; io_object++)
{ {
@ -66,15 +64,33 @@ pgstat_backend_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
instr_time time; instr_time time;
bktype_shstats->counts[io_object][io_context][io_op] += bktype_shstats->counts[io_object][io_context][io_op] +=
pendingent->counts[io_object][io_context][io_op]; pending_io->counts[io_object][io_context][io_op];
time = pendingent->pending_times[io_object][io_context][io_op]; time = pending_io->pending_times[io_object][io_context][io_op];
bktype_shstats->times[io_object][io_context][io_op] += bktype_shstats->times[io_object][io_context][io_op] +=
INSTR_TIME_GET_MICROSEC(time); INSTR_TIME_GET_MICROSEC(time);
} }
} }
} }
}
/*
* Wrapper routine to flush backend statistics.
*/
static bool
pgstat_flush_backend_entry(PgStat_EntryRef *entry_ref, bool nowait,
bits32 flags)
{
if (!pgstat_tracks_backend_bktype(MyBackendType))
return false;
if (!pgstat_lock_entry(entry_ref, nowait))
return false;
/* Flush requested statistics */
if (flags & PGSTAT_BACKEND_FLUSH_IO)
pgstat_flush_backend_entry_io(entry_ref);
pgstat_unlock_entry(entry_ref); pgstat_unlock_entry(entry_ref);
@ -82,10 +98,23 @@ pgstat_backend_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
} }
/* /*
* Simpler wrapper of pgstat_backend_flush_cb() * Callback to flush out locally pending backend statistics.
*
* If no stats have been recorded, this function returns false.
*/
bool
pgstat_backend_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
{
return pgstat_flush_backend_entry(entry_ref, nowait, PGSTAT_BACKEND_FLUSH_ALL);
}
/*
* Flush out locally pending backend statistics
*
* "flags" parameter controls which statistics to flush.
*/ */
void void
pgstat_flush_backend(bool nowait) pgstat_flush_backend(bool nowait, bits32 flags)
{ {
PgStat_EntryRef *entry_ref; PgStat_EntryRef *entry_ref;
@ -94,7 +123,7 @@ pgstat_flush_backend(bool nowait)
entry_ref = pgstat_get_entry_ref(PGSTAT_KIND_BACKEND, InvalidOid, entry_ref = pgstat_get_entry_ref(PGSTAT_KIND_BACKEND, InvalidOid,
MyProcNumber, false, NULL); MyProcNumber, false, NULL);
(void) pgstat_backend_flush_cb(entry_ref, nowait); (void) pgstat_flush_backend_entry(entry_ref, nowait, flags);
} }
/* /*
@ -119,9 +148,9 @@ pgstat_create_backend(ProcNumber procnum)
} }
/* /*
* Find or create a local PgStat_BackendPendingIO entry for proc number. * Find or create a local PgStat_BackendPending entry for proc number.
*/ */
PgStat_BackendPendingIO * PgStat_BackendPending *
pgstat_prep_backend_pending(ProcNumber procnum) pgstat_prep_backend_pending(ProcNumber procnum)
{ {
PgStat_EntryRef *entry_ref; PgStat_EntryRef *entry_ref;

View File

@ -81,10 +81,10 @@ pgstat_count_io_op_n(IOObject io_object, IOContext io_context, IOOp io_op, uint3
if (pgstat_tracks_backend_bktype(MyBackendType)) if (pgstat_tracks_backend_bktype(MyBackendType))
{ {
PgStat_PendingIO *entry_ref; PgStat_BackendPending *entry_ref;
entry_ref = pgstat_prep_backend_pending(MyProcNumber); entry_ref = pgstat_prep_backend_pending(MyProcNumber);
entry_ref->counts[io_object][io_context][io_op] += cnt; entry_ref->pending_io.counts[io_object][io_context][io_op] += cnt;
} }
PendingIOStats.counts[io_object][io_context][io_op] += cnt; PendingIOStats.counts[io_object][io_context][io_op] += cnt;
@ -151,10 +151,10 @@ pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op,
if (pgstat_tracks_backend_bktype(MyBackendType)) if (pgstat_tracks_backend_bktype(MyBackendType))
{ {
PgStat_PendingIO *entry_ref; PgStat_BackendPending *entry_ref;
entry_ref = pgstat_prep_backend_pending(MyProcNumber); entry_ref = pgstat_prep_backend_pending(MyProcNumber);
INSTR_TIME_ADD(entry_ref->pending_times[io_object][io_context][io_op], INSTR_TIME_ADD(entry_ref->pending_io.pending_times[io_object][io_context][io_op],
io_time); io_time);
} }
} }

View File

@ -264,7 +264,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
* VACUUM command has processed all tables and committed. * VACUUM command has processed all tables and committed.
*/ */
pgstat_flush_io(false); pgstat_flush_io(false);
pgstat_flush_backend(false); pgstat_flush_backend(false, PGSTAT_BACKEND_FLUSH_IO);
} }
/* /*
@ -351,7 +351,7 @@ pgstat_report_analyze(Relation rel,
/* see pgstat_report_vacuum() */ /* see pgstat_report_vacuum() */
pgstat_flush_io(false); pgstat_flush_io(false);
pgstat_flush_backend(false); pgstat_flush_backend(false, PGSTAT_BACKEND_FLUSH_IO);
} }
/* /*

View File

@ -1544,7 +1544,7 @@ pg_stat_get_backend_io(PG_FUNCTION_ARGS)
if (bktype == B_INVALID) if (bktype == B_INVALID)
return (Datum) 0; return (Datum) 0;
bktype_stats = &backend_stats->stats; bktype_stats = &backend_stats->io_stats;
/* /*
* In Assert builds, we can afford an extra loop through all of the * In Assert builds, we can afford an extra loop through all of the

View File

@ -375,15 +375,24 @@ typedef struct PgStat_IO
PgStat_BktypeIO stats[BACKEND_NUM_TYPES]; PgStat_BktypeIO stats[BACKEND_NUM_TYPES];
} PgStat_IO; } PgStat_IO;
/* Backend statistics store the same amount of IO data as PGSTAT_KIND_IO */
typedef PgStat_PendingIO PgStat_BackendPendingIO;
typedef struct PgStat_Backend typedef struct PgStat_Backend
{ {
TimestampTz stat_reset_timestamp; TimestampTz stat_reset_timestamp;
PgStat_BktypeIO stats; PgStat_BktypeIO io_stats;
} PgStat_Backend; } PgStat_Backend;
/* ---------
* PgStat_BackendPending Non-flushed backend stats.
* ---------
*/
typedef struct PgStat_BackendPending
{
/*
* Backend statistics store the same amount of IO data as PGSTAT_KIND_IO.
*/
PgStat_PendingIO pending_io;
} PgStat_BackendPending;
typedef struct PgStat_StatDBEntry typedef struct PgStat_StatDBEntry
{ {
PgStat_Counter xact_commit; PgStat_Counter xact_commit;

View File

@ -613,9 +613,12 @@ extern void pgstat_archiver_snapshot_cb(void);
* Functions in pgstat_backend.c * Functions in pgstat_backend.c
*/ */
extern void pgstat_flush_backend(bool nowait); /* flags for pgstat_flush_backend() */
#define PGSTAT_BACKEND_FLUSH_IO (1 << 0) /* Flush I/O statistics */
#define PGSTAT_BACKEND_FLUSH_ALL (PGSTAT_BACKEND_FLUSH_IO)
extern PgStat_BackendPendingIO *pgstat_prep_backend_pending(ProcNumber procnum); extern void pgstat_flush_backend(bool nowait, bits32 flags);
extern PgStat_BackendPending *pgstat_prep_backend_pending(ProcNumber procnum);
extern bool pgstat_backend_flush_cb(PgStat_EntryRef *entry_ref, bool nowait); extern bool pgstat_backend_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
extern void pgstat_backend_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts); extern void pgstat_backend_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts);

View File

@ -2140,7 +2140,7 @@ PgStatShared_Subscription
PgStatShared_Wal PgStatShared_Wal
PgStat_ArchiverStats PgStat_ArchiverStats
PgStat_Backend PgStat_Backend
PgStat_BackendPendingIO PgStat_BackendPending
PgStat_BackendSubEntry PgStat_BackendSubEntry
PgStat_BgWriterStats PgStat_BgWriterStats
PgStat_BktypeIO PgStat_BktypeIO