PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pgstat_backend.c
Go to the documentation of this file.
1/* -------------------------------------------------------------------------
2 *
3 * pgstat_backend.c
4 * Implementation of backend statistics.
5 *
6 * This file contains the implementation of backend statistics. It is kept
7 * separate from pgstat.c to enforce the line between the statistics access /
8 * storage implementation and the details about individual types of
9 * statistics.
10 *
11 * This statistics kind uses a proc number as object ID for the hash table
12 * of pgstats. Entries are created each time a process is spawned, and are
13 * dropped when the process exits. These are not written to the pgstats file
14 * on disk. Pending statistics are managed without direct interactions with
15 * PgStat_EntryRef->pending, relying on PendingBackendStats instead so as it
16 * is possible to report data within critical sections.
17 *
18 * Copyright (c) 2001-2026, PostgreSQL Global Development Group
19 *
20 * IDENTIFICATION
21 * src/backend/utils/activity/pgstat_backend.c
22 * -------------------------------------------------------------------------
23 */
24
25#include "postgres.h"
26
27#include "access/xlog.h"
28#include "executor/instrument.h"
29#include "storage/bufmgr.h"
30#include "storage/proc.h"
31#include "storage/procarray.h"
32#include "utils/memutils.h"
34
35/*
36 * Backend statistics counts waiting to be flushed out. These counters may be
37 * reported within critical sections so we use static memory in order to avoid
38 * memory allocation.
39 */
41static bool backend_has_iostats = false;
42static bool backend_has_lockstats = false;
43
44/*
45 * WAL usage counters saved from pgWalUsage at the previous call to
46 * pgstat_flush_backend(). This is used to calculate how much WAL usage
47 * happens between pgstat_flush_backend() calls, by subtracting the
48 * previous counters from the current ones.
49 */
51
52/*
53 * Utility routines to report I/O stats for backends, kept here to avoid
54 * exposing PendingBackendStats to the outside world.
55 */
56void
73
74void
89
90/*
91 * Utility routines to report lock stats for backends, kept here to avoid
92 * exposing PendingBackendStats to the outside world.
93 */
94void
108
109void
122
123/*
124 * Returns statistics of a backend by proc number.
125 */
137
138/*
139 * Returns statistics of a backend by pid.
140 *
141 * This routine includes sanity checks to ensure that the backend exists and
142 * is running. "bktype" can be optionally defined to return the BackendType
143 * of the backend whose statistics are returned.
144 */
147{
148 PGPROC *proc;
150 ProcNumber procNumber;
152
153 proc = BackendPidGetProc(pid);
154 if (bktype)
155 *bktype = B_INVALID;
156
157 /* this could be an auxiliary process */
158 if (!proc)
159 proc = AuxiliaryPidGetProc(pid);
160
161 if (!proc)
162 return NULL;
163
164 procNumber = GetNumberFromPGProc(proc);
165
167 if (!beentry)
168 return NULL;
169
170 /* check if the backend type tracks statistics */
171 if (!pgstat_tracks_backend_bktype(beentry->st_backendType))
172 return NULL;
173
174 /* if PID does not match, leave */
175 if (beentry->st_procpid != pid)
176 return NULL;
177
178 if (bktype)
179 *bktype = beentry->st_backendType;
180
181 /*
182 * Retrieve the entry. Note that "beentry" may be freed depending on the
183 * value of stats_fetch_consistency, so do not access it from this point.
184 */
186 if (!backend_stats)
187 {
188 if (bktype)
189 *bktype = B_INVALID;
190 return NULL;
191 }
192
193 return backend_stats;
194}
195
196/*
197 * Flush out locally pending backend IO statistics. Locking is managed
198 * by the caller.
199 */
200static void
202{
205 PgStat_PendingIO pending_io;
206
207 /*
208 * This function can be called even if nothing at all has happened for IO
209 * statistics. In this case, avoid unnecessarily modifying the stats
210 * entry.
211 */
213 return;
214
216 bktype_shstats = &shbackendent->stats.io_stats;
217 pending_io = PendingBackendStats.pending_io;
218
220 {
222 {
223 for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++)
224 {
225 instr_time time;
226
228 pending_io.counts[io_object][io_context][io_op];
230 pending_io.bytes[io_object][io_context][io_op];
231 time = pending_io.pending_times[io_object][io_context][io_op];
232
235 }
236 }
237 }
238
239 /*
240 * Clear out the statistics buffer, so it can be re-used.
241 */
243
244 backend_has_iostats = false;
245}
246
247/*
248 * To determine whether WAL usage happened.
249 */
250static inline bool
255
256/*
257 * Flush out locally pending backend WAL statistics. Locking is managed
258 * by the caller.
259 */
260static void
262{
266
267 /*
268 * This function can be called even if nothing at all has happened for WAL
269 * statistics. In this case, avoid unnecessarily modifying the stats
270 * entry.
271 */
273 return;
274
276 bktype_shstats = &shbackendent->stats.wal_counters;
277
278 /*
279 * Calculate how much WAL usage counters were increased by subtracting the
280 * previous counters from the current ones.
281 */
283
284#define WALSTAT_ACC(fld, var_to_add) \
285 (bktype_shstats->fld += var_to_add.fld)
286 WALSTAT_ACC(wal_buffers_full, wal_usage_diff);
287 WALSTAT_ACC(wal_records, wal_usage_diff);
288 WALSTAT_ACC(wal_fpi, wal_usage_diff);
289 WALSTAT_ACC(wal_bytes, wal_usage_diff);
290 WALSTAT_ACC(wal_fpi_bytes, wal_usage_diff);
291#undef WALSTAT_ACC
292
293 /*
294 * Save the current counters for the subsequent calculation of WAL usage.
295 */
297}
298
299/*
300 * Flush out locally pending backend lock statistics. Locking is managed
301 * by the caller.
302 */
303static void
305{
308
310 return;
311
313 bktype_shstats = &shbackendent->stats.lock_stats;
314
315 for (int i = 0; i <= LOCKTAG_LAST_TYPE; i++)
316 {
317#define LOCKSTAT_ACC(fld) \
318 (bktype_shstats->stats[i].fld += PendingBackendStats.pending_lock.stats[i].fld)
319 LOCKSTAT_ACC(waits);
320 LOCKSTAT_ACC(wait_time);
321 LOCKSTAT_ACC(fastpath_exceeded);
322#undef LOCKSTAT_ACC
323 }
324
326 backend_has_lockstats = false;
327}
328
329/*
330 * Flush out locally pending backend statistics
331 *
332 * "flags" parameter controls which statistics to flush. Returns true
333 * if some statistics could not be flushed due to lock contention.
334 */
335bool
336pgstat_flush_backend(bool nowait, uint32 flags)
337{
338 PgStat_EntryRef *entry_ref;
339 bool has_pending_data = false;
340
342 return false;
343
344 /* Some IO data pending? */
346 has_pending_data = true;
347
348 /* Some WAL data pending? */
349 if ((flags & PGSTAT_BACKEND_FLUSH_WAL) &&
351 has_pending_data = true;
352
353 /* Some lock data pending? */
355 has_pending_data = true;
356
357 if (!has_pending_data)
358 return false;
359
361 MyProcNumber, nowait);
362 if (!entry_ref)
363 return true;
364
365 /* Flush requested statistics */
366 if (flags & PGSTAT_BACKEND_FLUSH_IO)
368
369 if (flags & PGSTAT_BACKEND_FLUSH_WAL)
371
372 if (flags & PGSTAT_BACKEND_FLUSH_LOCK)
374
375 pgstat_unlock_entry(entry_ref);
376
377 return false;
378}
379
380/*
381 * Callback to flush out locally pending backend statistics.
382 *
383 * If some stats could not be flushed due to lock contention, return true.
384 */
385bool
390
391/*
392 * Create backend statistics entry for proc number.
393 */
394void
396{
397 PgStat_EntryRef *entry_ref;
399
401 procnum, false);
403
404 /*
405 * NB: need to accept that there might be stats from an older backend,
406 * e.g. if we previously used this proc number.
407 */
408 memset(&shstatent->stats, 0, sizeof(shstatent->stats));
409 pgstat_unlock_entry(entry_ref);
410
412 backend_has_iostats = false;
413 backend_has_lockstats = false;
414
415 /*
416 * Initialize prevBackendWalUsage with pgWalUsage so that
417 * pgstat_backend_flush_cb() can calculate how much pgWalUsage counters
418 * are increased by subtracting prevBackendWalUsage from pgWalUsage.
419 */
421}
422
423/*
424 * Backend statistics are not collected for all BackendTypes.
425 *
426 * The following BackendTypes do not participate in the backend stats
427 * subsystem:
428 * - The same and for the same reasons as in pgstat_tracks_io_bktype().
429 * - B_BG_WRITER, B_CHECKPOINTER, B_STARTUP and B_AUTOVAC_LAUNCHER because their
430 * I/O stats are already visible in pg_stat_io and there is only one of those.
431 *
432 * Function returns true if BackendType participates in the backend stats
433 * subsystem and false if it does not.
434 *
435 * When adding a new BackendType, also consider adding relevant restrictions to
436 * pgstat_tracks_io_object() and pgstat_tracks_io_op().
437 */
438bool
440{
441 /*
442 * List every type so that new backend types trigger a warning about
443 * needing to adjust this switch.
444 */
445 switch (bktype)
446 {
447 case B_INVALID:
450 case B_ARCHIVER:
451 case B_LOGGER:
452 case B_BG_WRITER:
453 case B_CHECKPOINTER:
454 case B_IO_WORKER:
455 case B_STARTUP:
458 return false;
459
460 case B_AUTOVAC_WORKER:
461 case B_BACKEND:
462 case B_BG_WORKER:
465 case B_WAL_RECEIVER:
466 case B_WAL_SENDER:
467 case B_WAL_SUMMARIZER:
468 case B_WAL_WRITER:
469 return true;
470 }
471
472 return false;
473}
474
475void
477{
478 ((PgStatShared_Backend *) header)->stats.stat_reset_timestamp = ts;
479}
PgBackendStatus * pgstat_get_beentry_by_proc_number(ProcNumber procNumber)
bool track_io_timing
Definition bufmgr.c:192
uint8_t uint8
Definition c.h:678
#define Assert(condition)
Definition c.h:999
uint64_t uint64
Definition c.h:681
uint32_t uint32
Definition c.h:680
#define MemSet(start, val, len)
Definition c.h:1163
int64 TimestampTz
Definition timestamp.h:39
ProcNumber MyProcNumber
Definition globals.c:92
#define INSTR_TIME_ADD(x, y)
Definition instr_time.h:438
#define INSTR_TIME_GET_MICROSEC(t)
Definition instr_time.h:462
WalUsage pgWalUsage
Definition instrument.c:27
void WalUsageAccumDiff(WalUsage *dst, const WalUsage *add, const WalUsage *sub)
Definition instrument.c:367
int i
Definition isn.c:77
#define LOCKTAG_LAST_TYPE
Definition locktag.h:52
BackendType
Definition miscadmin.h:341
@ B_WAL_SUMMARIZER
Definition miscadmin.h:370
@ B_WAL_WRITER
Definition miscadmin.h:371
@ B_WAL_RECEIVER
Definition miscadmin.h:369
@ B_CHECKPOINTER
Definition miscadmin.h:366
@ B_DATACHECKSUMSWORKER_WORKER
Definition miscadmin.h:374
@ B_WAL_SENDER
Definition miscadmin.h:350
@ B_IO_WORKER
Definition miscadmin.h:367
@ B_LOGGER
Definition miscadmin.h:380
@ B_STARTUP
Definition miscadmin.h:368
@ B_DATACHECKSUMSWORKER_LAUNCHER
Definition miscadmin.h:373
@ B_BG_WORKER
Definition miscadmin.h:349
@ B_INVALID
Definition miscadmin.h:342
@ B_STANDALONE_BACKEND
Definition miscadmin.h:353
@ B_BG_WRITER
Definition miscadmin.h:365
@ B_BACKEND
Definition miscadmin.h:345
@ B_ARCHIVER
Definition miscadmin.h:364
@ B_AUTOVAC_LAUNCHER
Definition miscadmin.h:347
@ B_SLOTSYNC_WORKER
Definition miscadmin.h:351
@ B_DEAD_END_BACKEND
Definition miscadmin.h:346
@ B_AUTOVAC_WORKER
Definition miscadmin.h:348
BackendType MyBackendType
Definition miscinit.c:65
void * pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid, bool *may_free)
Definition pgstat.c:962
bool pgstat_report_fixed
Definition pgstat.c:219
IOObject
Definition pgstat.h:280
#define IOOP_NUM_TYPES
Definition pgstat.h:323
IOContext
Definition pgstat.h:289
#define IOCONTEXT_NUM_TYPES
Definition pgstat.h:297
IOOp
Definition pgstat.h:309
int64 PgStat_Counter
Definition pgstat.h:71
#define IOOBJECT_NUM_TYPES
Definition pgstat.h:286
void pgstat_create_backend(ProcNumber procnum)
static bool backend_has_lockstats
static void pgstat_flush_backend_entry_wal(PgStat_EntryRef *entry_ref)
void pgstat_count_backend_lock_waits(uint8 locktag_type, PgStat_Counter usecs)
static PgStat_BackendPending PendingBackendStats
bool pgstat_tracks_backend_bktype(BackendType bktype)
#define WALSTAT_ACC(fld, var_to_add)
static void pgstat_flush_backend_entry_io(PgStat_EntryRef *entry_ref)
void pgstat_count_backend_io_op(IOObject io_object, IOContext io_context, IOOp io_op, uint32 cnt, uint64 bytes)
static bool pgstat_backend_wal_have_pending(void)
static bool backend_has_iostats
bool pgstat_flush_backend(bool nowait, uint32 flags)
void pgstat_count_backend_lock_fastpath_exceeded(uint8 locktag_type)
static void pgstat_flush_backend_entry_lock(PgStat_EntryRef *entry_ref)
#define LOCKSTAT_ACC(fld)
void pgstat_backend_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)
static WalUsage prevBackendWalUsage
PgStat_Backend * pgstat_fetch_stat_backend_by_pid(int pid, BackendType *bktype)
void pgstat_count_backend_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time io_time)
bool pgstat_backend_flush_cb(bool nowait)
PgStat_Backend * pgstat_fetch_stat_backend(ProcNumber procNumber)
#define PGSTAT_BACKEND_FLUSH_LOCK
#define PGSTAT_BACKEND_FLUSH_ALL
#define PGSTAT_BACKEND_FLUSH_IO
#define PGSTAT_BACKEND_FLUSH_WAL
bool pgstat_tracks_io_op(BackendType bktype, IOObject io_object, IOContext io_context, IOOp io_op)
Definition pgstat_io.c:479
#define PGSTAT_KIND_BACKEND
Definition pgstat_kind.h:32
void pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
PgStat_EntryRef * pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, uint64 objid, bool nowait)
#define InvalidOid
static int fb(int x)
#define GetNumberFromPGProc(proc)
Definition proc.h:505
PGPROC * BackendPidGetProc(int pid)
Definition procarray.c:3156
int ProcNumber
Definition procnumber.h:24
PGPROC * AuxiliaryPidGetProc(int pid)
Definition proc.c:1130
Definition proc.h:179
PgStat_PendingLock pending_lock
Definition pgstat.h:544
PgStat_PendingIO pending_io
Definition pgstat.h:538
PgStatShared_Common * shared_stats
PgStat_Counter waits
Definition pgstat.h:351
PgStat_Counter wait_time
Definition pgstat.h:352
PgStat_Counter fastpath_exceeded
Definition pgstat.h:353
PgStat_Counter counts[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition pgstat.h:339
uint64 bytes[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition pgstat.h:338
instr_time pending_times[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition pgstat.h:340
PgStat_LockEntry stats[LOCKTAG_LAST_TYPE+1]
Definition pgstat.h:358
int64 wal_records
Definition instrument.h:53
bool track_wal_io_timing
Definition xlog.c:144