Skip to content

Commit fc415ed

Browse files
committed
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
1 parent 2e62fa6 commit fc415ed

File tree

5 files changed

+119
-40
lines changed

5 files changed

+119
-40
lines changed

src/backend/utils/activity/pgstat.c

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,8 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
411411
.shared_data_off = offsetof(PgStatShared_IO, stats),
412412
.shared_data_len = sizeof(((PgStatShared_IO *) 0)->stats),
413413

414+
.flush_fixed_cb = pgstat_io_flush_cb,
415+
.have_fixed_pending_cb = pgstat_io_have_pending_cb,
414416
.init_shmem_cb = pgstat_io_init_shmem_cb,
415417
.reset_all_cb = pgstat_io_reset_all_cb,
416418
.snapshot_cb = pgstat_io_snapshot_cb,
@@ -426,6 +428,8 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
426428
.shared_data_off = offsetof(PgStatShared_SLRU, stats),
427429
.shared_data_len = sizeof(((PgStatShared_SLRU *) 0)->stats),
428430

431+
.flush_fixed_cb = pgstat_slru_flush_cb,
432+
.have_fixed_pending_cb = pgstat_slru_have_pending_cb,
429433
.init_shmem_cb = pgstat_slru_init_shmem_cb,
430434
.reset_all_cb = pgstat_slru_reset_all_cb,
431435
.snapshot_cb = pgstat_slru_snapshot_cb,
@@ -442,6 +446,8 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
442446
.shared_data_len = sizeof(((PgStatShared_Wal *) 0)->stats),
443447

444448
.init_backend_cb = pgstat_wal_init_backend_cb,
449+
.flush_fixed_cb = pgstat_wal_flush_cb,
450+
.have_fixed_pending_cb = pgstat_wal_have_pending_cb,
445451
.init_shmem_cb = pgstat_wal_init_shmem_cb,
446452
.reset_all_cb = pgstat_wal_reset_all_cb,
447453
.snapshot_cb = pgstat_wal_snapshot_cb,
@@ -671,13 +677,37 @@ pgstat_report_stat(bool force)
671677
}
672678

673679
/* Don't expend a clock check if nothing to do */
674-
if (dlist_is_empty(&pgStatPending) &&
675-
!have_iostats &&
676-
!have_slrustats &&
677-
!pgstat_have_pending_wal())
680+
if (dlist_is_empty(&pgStatPending))
678681
{
679-
Assert(pending_since == 0);
680-
return 0;
682+
bool do_flush = false;
683+
684+
/* Check for pending fixed-numbered stats */
685+
for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
686+
{
687+
const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
688+
689+
if (!kind_info)
690+
continue;
691+
if (!kind_info->fixed_amount)
692+
{
693+
Assert(kind_info->have_fixed_pending_cb == NULL);
694+
continue;
695+
}
696+
if (!kind_info->have_fixed_pending_cb)
697+
continue;
698+
699+
if (kind_info->have_fixed_pending_cb())
700+
{
701+
do_flush = true;
702+
break;
703+
}
704+
}
705+
706+
if (!do_flush)
707+
{
708+
Assert(pending_since == 0);
709+
return 0;
710+
}
681711
}
682712

683713
/*
@@ -730,14 +760,23 @@ pgstat_report_stat(bool force)
730760
/* flush database / relation / function / ... stats */
731761
partial_flush |= pgstat_flush_pending_entries(nowait);
732762

733-
/* flush IO stats */
734-
partial_flush |= pgstat_flush_io(nowait);
763+
/* flush of fixed-numbered stats */
764+
for (PgStat_Kind kind = PGSTAT_KIND_MIN; kind <= PGSTAT_KIND_MAX; kind++)
765+
{
766+
const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
735767

736-
/* flush wal stats */
737-
partial_flush |= pgstat_flush_wal(nowait);
768+
if (!kind_info)
769+
continue;
770+
if (!kind_info->fixed_amount)
771+
{
772+
Assert(kind_info->flush_fixed_cb == NULL);
773+
continue;
774+
}
775+
if (!kind_info->flush_fixed_cb)
776+
continue;
738777

739-
/* flush SLRU stats */
740-
partial_flush |= pgstat_slru_flush(nowait);
778+
partial_flush |= kind_info->flush_fixed_cb(nowait);
779+
}
741780

742781
last_flush = now;
743782

src/backend/utils/activity/pgstat_io.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ typedef struct PgStat_PendingIO
2929

3030

3131
static PgStat_PendingIO PendingIOStats;
32-
bool have_iostats = false;
32+
static bool have_iostats = false;
3333

3434

3535
/*
@@ -161,6 +161,24 @@ pgstat_fetch_stat_io(void)
161161
return &pgStatLocal.snapshot.io;
162162
}
163163

164+
/*
165+
* Check if there any IO stats waiting for flush.
166+
*/
167+
bool
168+
pgstat_io_have_pending_cb(void)
169+
{
170+
return have_iostats;
171+
}
172+
173+
/*
174+
* Simpler wrapper of pgstat_io_flush_cb()
175+
*/
176+
void
177+
pgstat_flush_io(bool nowait)
178+
{
179+
(void) pgstat_io_flush_cb(nowait);
180+
}
181+
164182
/*
165183
* Flush out locally pending IO statistics
166184
*
@@ -170,7 +188,7 @@ pgstat_fetch_stat_io(void)
170188
* acquired. Otherwise, return false.
171189
*/
172190
bool
173-
pgstat_flush_io(bool nowait)
191+
pgstat_io_flush_cb(bool nowait)
174192
{
175193
LWLock *bktype_lock;
176194
PgStat_BktypeIO *bktype_shstats;

src/backend/utils/activity/pgstat_slru.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static void pgstat_reset_slru_counter_internal(int index, TimestampTz ts);
3232
* in order to avoid memory allocation.
3333
*/
3434
static PgStat_SLRUStats pending_SLRUStats[SLRU_NUM_ELEMENTS];
35-
bool have_slrustats = false;
35+
static bool have_slrustats = false;
3636

3737

3838
/*
@@ -143,6 +143,15 @@ pgstat_get_slru_index(const char *name)
143143
return (SLRU_NUM_ELEMENTS - 1);
144144
}
145145

146+
/*
147+
* Check if there are any SLRU stats entries waiting for flush.
148+
*/
149+
bool
150+
pgstat_slru_have_pending_cb(void)
151+
{
152+
return have_slrustats;
153+
}
154+
146155
/*
147156
* Flush out locally pending SLRU stats entries
148157
*
@@ -153,7 +162,7 @@ pgstat_get_slru_index(const char *name)
153162
* acquired. Otherwise return false.
154163
*/
155164
bool
156-
pgstat_slru_flush(bool nowait)
165+
pgstat_slru_flush_cb(bool nowait)
157166
{
158167
PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
159168
int i;

src/backend/utils/activity/pgstat_wal.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@ pgstat_fetch_stat_wal(void)
7171
return &pgStatLocal.snapshot.wal;
7272
}
7373

74+
/*
75+
* Simple wrapper of pgstat_wal_flush_cb()
76+
*/
77+
void
78+
pgstat_flush_wal(bool nowait)
79+
{
80+
(void) pgstat_wal_flush_cb(nowait);
81+
}
82+
7483
/*
7584
* Calculate how much WAL usage counters have increased by subtracting the
7685
* previous counters from the current ones.
@@ -79,7 +88,7 @@ pgstat_fetch_stat_wal(void)
7988
* acquired. Otherwise return false.
8089
*/
8190
bool
82-
pgstat_flush_wal(bool nowait)
91+
pgstat_wal_flush_cb(bool nowait)
8392
{
8493
PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
8594
WalUsage wal_usage_diff = {0};
@@ -92,7 +101,7 @@ pgstat_flush_wal(bool nowait)
92101
* This function can be called even if nothing at all has happened. Avoid
93102
* taking lock for nothing in that case.
94103
*/
95-
if (!pgstat_have_pending_wal())
104+
if (!pgstat_wal_have_pending_cb())
96105
return false;
97106

98107
/*
@@ -141,8 +150,8 @@ void
141150
pgstat_wal_init_backend_cb(void)
142151
{
143152
/*
144-
* Initialize prevWalUsage with pgWalUsage so that pgstat_flush_wal() can
145-
* calculate how much pgWalUsage counters are increased by subtracting
153+
* Initialize prevWalUsage with pgWalUsage so that pgstat_wal_flush_cb()
154+
* can calculate how much pgWalUsage counters are increased by subtracting
146155
* prevWalUsage from pgWalUsage.
147156
*/
148157
prevWalUsage = pgWalUsage;
@@ -156,7 +165,7 @@ pgstat_wal_init_backend_cb(void)
156165
* data pages.
157166
*/
158167
bool
159-
pgstat_have_pending_wal(void)
168+
pgstat_wal_have_pending_cb(void)
160169
{
161170
return pgWalUsage.wal_records != prevWalUsage.wal_records ||
162171
PendingWalStats.wal_write != 0 ||

src/include/utils/pgstat_internal.h

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ typedef struct PgStat_KindInfo
237237

238238
/*
239239
* For variable-numbered stats: flush pending stats. Required if pending
240-
* data is used.
240+
* data is used. See flush_fixed_cb for fixed-numbered stats.
241241
*/
242242
bool (*flush_pending_cb) (PgStat_EntryRef *sr, bool nowait);
243243

@@ -265,6 +265,19 @@ typedef struct PgStat_KindInfo
265265
*/
266266
void (*init_shmem_cb) (void *stats);
267267

268+
/*
269+
* For fixed-numbered statistics: Flush pending stats. Returns true if
270+
* some of the stats could not be flushed, due to lock contention for
271+
* example. Optional.
272+
*/
273+
bool (*flush_fixed_cb) (bool nowait);
274+
275+
/*
276+
* For fixed-numbered statistics: Check for pending stats in need of
277+
* flush. Returns true if there are any stats pending for flush. Optional.
278+
*/
279+
bool (*have_fixed_pending_cb) (void);
280+
268281
/*
269282
* For fixed-numbered statistics: Reset All.
270283
*/
@@ -609,7 +622,10 @@ extern bool pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
609622
* Functions in pgstat_io.c
610623
*/
611624

612-
extern bool pgstat_flush_io(bool nowait);
625+
extern void pgstat_flush_io(bool nowait);
626+
627+
extern bool pgstat_io_have_pending_cb(void);
628+
extern bool pgstat_io_flush_cb(bool nowait);
613629
extern void pgstat_io_init_shmem_cb(void *stats);
614630
extern void pgstat_io_reset_all_cb(TimestampTz ts);
615631
extern void pgstat_io_snapshot_cb(void);
@@ -668,7 +684,8 @@ extern PgStatShared_Common *pgstat_init_entry(PgStat_Kind kind,
668684
* Functions in pgstat_slru.c
669685
*/
670686

671-
extern bool pgstat_slru_flush(bool nowait);
687+
extern bool pgstat_slru_have_pending_cb(void);
688+
extern bool pgstat_slru_flush_cb(bool nowait);
672689
extern void pgstat_slru_init_shmem_cb(void *stats);
673690
extern void pgstat_slru_reset_all_cb(TimestampTz ts);
674691
extern void pgstat_slru_snapshot_cb(void);
@@ -678,10 +695,11 @@ extern void pgstat_slru_snapshot_cb(void);
678695
* Functions in pgstat_wal.c
679696
*/
680697

681-
extern bool pgstat_flush_wal(bool nowait);
682-
extern bool pgstat_have_pending_wal(void);
698+
extern void pgstat_flush_wal(bool nowait);
683699

684700
extern void pgstat_wal_init_backend_cb(void);
701+
extern bool pgstat_wal_have_pending_cb(void);
702+
extern bool pgstat_wal_flush_cb(bool nowait);
685703
extern void pgstat_wal_init_shmem_cb(void *stats);
686704
extern void pgstat_wal_reset_all_cb(TimestampTz ts);
687705
extern void pgstat_wal_snapshot_cb(void);
@@ -711,20 +729,6 @@ extern void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
711729
extern PGDLLIMPORT PgStat_LocalState pgStatLocal;
712730

713731

714-
/*
715-
* Variables in pgstat_io.c
716-
*/
717-
718-
extern PGDLLIMPORT bool have_iostats;
719-
720-
721-
/*
722-
* Variables in pgstat_slru.c
723-
*/
724-
725-
extern PGDLLIMPORT bool have_slrustats;
726-
727-
728732
/*
729733
* Implementation of inline functions declared above.
730734
*/

0 commit comments

Comments
 (0)