mirror of
https://github.com/postgres/postgres.git
synced 2025-11-21 00:42:43 +03:00
Add callbacks to control flush of fixed-numbered stats
This commit adds two callbacks in pgstats to have a better control of the flush timing of pgstat_report_stat(), whose operation depends on the three PGSTAT_*_INTERVAL variables: - have_fixed_pending_cb(), to check if a stats kind has any pending data waiting for a flush. This is used as a fast path if there are no pending statistics to flush, and this check is done for fixed-numbered statistics only if there are no variable-numbered statistics to flush. A flush will need to happen if at least one callback reports any pending data. - flush_fixed_cb(), to do the actual flush. These callbacks are currently used by the SLRU, WAL and IO statistics, generalizing the concept for all stats kinds (builtin and custom). The SLRU and IO stats relied each on one global variable to determine whether a flush should happen; these are now local to pgstat_slru.c and pgstat_io.c, cleaning up a bit how the pending flush states are tracked in pgstat.c. pgstat_flush_io() and pgstat_flush_wal() are still required, but we do not need to check their return result anymore. Reviewed-by: Bertrand Drouvot, Kyotaro Horiguchi Discussion: https://postgr.es/m/ZtaVO0N-aTwiAk3w@paquier.xyz
This commit is contained in:
@@ -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,
|
||||
@@ -442,6 +446,8 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
|
||||
.shared_data_len = sizeof(((PgStatShared_Wal *) 0)->stats),
|
||||
|
||||
.init_backend_cb = pgstat_wal_init_backend_cb,
|
||||
.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,
|
||||
@@ -671,13 +677,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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -730,14 +760,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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_wal_init_backend_cb(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_wal_init_backend_cb(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 ||
|
||||
|
||||
Reference in New Issue
Block a user