PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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-2025, 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 "storage/bufmgr.h"
29#include "storage/proc.h"
30#include "storage/procarray.h"
31#include "utils/memutils.h"
33
34/*
35 * Backend statistics counts waiting to be flushed out. These counters may be
36 * reported within critical sections so we use static memory in order to avoid
37 * memory allocation.
38 */
40static bool backend_has_iostats = false;
41
42/*
43 * WAL usage counters saved from pgWalUsage at the previous call to
44 * pgstat_report_wal(). This is used to calculate how much WAL usage
45 * happens between pgstat_report_wal() calls, by subtracting the previous
46 * counters from the current ones.
47 */
49
50/*
51 * Utility routines to report I/O stats for backends, kept here to avoid
52 * exposing PendingBackendStats to the outside world.
53 */
54void
56 IOOp io_op, instr_time io_time)
57{
59
61 return;
62
63 Assert(pgstat_tracks_io_op(MyBackendType, io_object, io_context, io_op));
64
65 INSTR_TIME_ADD(PendingBackendStats.pending_io.pending_times[io_object][io_context][io_op],
66 io_time);
67
69}
70
71void
73 IOOp io_op, uint32 cnt, uint64 bytes)
74{
76 return;
77
78 Assert(pgstat_tracks_io_op(MyBackendType, io_object, io_context, io_op));
79
80 PendingBackendStats.pending_io.counts[io_object][io_context][io_op] += cnt;
81 PendingBackendStats.pending_io.bytes[io_object][io_context][io_op] += bytes;
82
84}
85
86/*
87 * Returns statistics of a backend by proc number.
88 */
91{
92 PgStat_Backend *backend_entry;
93
95 InvalidOid, procNumber);
96
97 return backend_entry;
98}
99
100/*
101 * Returns statistics of a backend by pid.
102 *
103 * This routine includes sanity checks to ensure that the backend exists and
104 * is running. "bktype" can be optionally defined to return the BackendType
105 * of the backend whose statistics are returned.
106 */
109{
110 PGPROC *proc;
111 PgBackendStatus *beentry;
112 ProcNumber procNumber;
113 PgStat_Backend *backend_stats;
114
115 proc = BackendPidGetProc(pid);
116 if (bktype)
117 *bktype = B_INVALID;
118
119 /* this could be an auxiliary process */
120 if (!proc)
121 proc = AuxiliaryPidGetProc(pid);
122
123 if (!proc)
124 return NULL;
125
126 procNumber = GetNumberFromPGProc(proc);
127
128 beentry = pgstat_get_beentry_by_proc_number(procNumber);
129 if (!beentry)
130 return NULL;
131
132 /* check if the backend type tracks statistics */
134 return NULL;
135
136 /* if PID does not match, leave */
137 if (beentry->st_procpid != pid)
138 return NULL;
139
140 if (bktype)
141 *bktype = beentry->st_backendType;
142
143 /*
144 * Retrieve the entry. Note that "beentry" may be freed depending on the
145 * value of stats_fetch_consistency, so do not access it from this point.
146 */
147 backend_stats = pgstat_fetch_stat_backend(procNumber);
148 if (!backend_stats)
149 {
150 if (bktype)
151 *bktype = B_INVALID;
152 return NULL;
153 }
154
155 return backend_stats;
156}
157
158/*
159 * Flush out locally pending backend IO statistics. Locking is managed
160 * by the caller.
161 */
162static void
164{
165 PgStatShared_Backend *shbackendent;
166 PgStat_BktypeIO *bktype_shstats;
167 PgStat_PendingIO pending_io;
168
169 /*
170 * This function can be called even if nothing at all has happened for IO
171 * statistics. In this case, avoid unnecessarily modifying the stats
172 * entry.
173 */
175 return;
176
177 shbackendent = (PgStatShared_Backend *) entry_ref->shared_stats;
178 bktype_shstats = &shbackendent->stats.io_stats;
179 pending_io = PendingBackendStats.pending_io;
180
181 for (int io_object = 0; io_object < IOOBJECT_NUM_TYPES; io_object++)
182 {
183 for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++)
184 {
185 for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++)
186 {
187 instr_time time;
188
189 bktype_shstats->counts[io_object][io_context][io_op] +=
190 pending_io.counts[io_object][io_context][io_op];
191 bktype_shstats->bytes[io_object][io_context][io_op] +=
192 pending_io.bytes[io_object][io_context][io_op];
193 time = pending_io.pending_times[io_object][io_context][io_op];
194
195 bktype_shstats->times[io_object][io_context][io_op] +=
197 }
198 }
199 }
200
201 /*
202 * Clear out the statistics buffer, so it can be re-used.
203 */
205
206 backend_has_iostats = false;
207}
208
209/*
210 * To determine whether WAL usage happened.
211 */
212static inline bool
214{
216}
217
218/*
219 * Flush out locally pending backend WAL statistics. Locking is managed
220 * by the caller.
221 */
222static void
224{
225 PgStatShared_Backend *shbackendent;
226 PgStat_WalCounters *bktype_shstats;
227 WalUsage wal_usage_diff = {0};
228
229 /*
230 * This function can be called even if nothing at all has happened for WAL
231 * statistics. In this case, avoid unnecessarily modifying the stats
232 * entry.
233 */
235 return;
236
237 shbackendent = (PgStatShared_Backend *) entry_ref->shared_stats;
238 bktype_shstats = &shbackendent->stats.wal_counters;
239
240 /*
241 * Calculate how much WAL usage counters were increased by subtracting the
242 * previous counters from the current ones.
243 */
245
246#define WALSTAT_ACC(fld, var_to_add) \
247 (bktype_shstats->fld += var_to_add.fld)
248 WALSTAT_ACC(wal_buffers_full, wal_usage_diff);
249 WALSTAT_ACC(wal_records, wal_usage_diff);
250 WALSTAT_ACC(wal_fpi, wal_usage_diff);
251 WALSTAT_ACC(wal_bytes, wal_usage_diff);
252#undef WALSTAT_ACC
253
254 /*
255 * Save the current counters for the subsequent calculation of WAL usage.
256 */
258}
259
260/*
261 * Flush out locally pending backend statistics
262 *
263 * "flags" parameter controls which statistics to flush. Returns true
264 * if some statistics could not be flushed due to lock contention.
265 */
266bool
267pgstat_flush_backend(bool nowait, bits32 flags)
268{
269 PgStat_EntryRef *entry_ref;
270 bool has_pending_data = false;
271
273 return false;
274
275 /* Some IO data pending? */
277 has_pending_data = true;
278
279 /* Some WAL data pending? */
280 if ((flags & PGSTAT_BACKEND_FLUSH_WAL) &&
282 has_pending_data = true;
283
284 if (!has_pending_data)
285 return false;
286
288 MyProcNumber, nowait);
289 if (!entry_ref)
290 return true;
291
292 /* Flush requested statistics */
293 if (flags & PGSTAT_BACKEND_FLUSH_IO)
295
296 if (flags & PGSTAT_BACKEND_FLUSH_WAL)
298
299 pgstat_unlock_entry(entry_ref);
300
301 return false;
302}
303
304/*
305 * Check if there are any backend stats waiting for flush.
306 */
307bool
309{
311 return false;
312
314}
315
316/*
317 * Callback to flush out locally pending backend statistics.
318 *
319 * If some stats could not be flushed due to lock contention, return true.
320 */
321bool
323{
325}
326
327/*
328 * Create backend statistics entry for proc number.
329 */
330void
332{
333 PgStat_EntryRef *entry_ref;
334 PgStatShared_Backend *shstatent;
335
337 MyProcNumber, false);
338 shstatent = (PgStatShared_Backend *) entry_ref->shared_stats;
339
340 /*
341 * NB: need to accept that there might be stats from an older backend,
342 * e.g. if we previously used this proc number.
343 */
344 memset(&shstatent->stats, 0, sizeof(shstatent->stats));
345 pgstat_unlock_entry(entry_ref);
346
348 backend_has_iostats = false;
349
350 /*
351 * Initialize prevBackendWalUsage with pgWalUsage so that
352 * pgstat_backend_flush_cb() can calculate how much pgWalUsage counters
353 * are increased by subtracting prevBackendWalUsage from pgWalUsage.
354 */
356}
357
358/*
359 * Backend statistics are not collected for all BackendTypes.
360 *
361 * The following BackendTypes do not participate in the backend stats
362 * subsystem:
363 * - The same and for the same reasons as in pgstat_tracks_io_bktype().
364 * - B_BG_WRITER, B_CHECKPOINTER, B_STARTUP and B_AUTOVAC_LAUNCHER because their
365 * I/O stats are already visible in pg_stat_io and there is only one of those.
366 *
367 * Function returns true if BackendType participates in the backend stats
368 * subsystem and false if it does not.
369 *
370 * When adding a new BackendType, also consider adding relevant restrictions to
371 * pgstat_tracks_io_object() and pgstat_tracks_io_op().
372 */
373bool
375{
376 /*
377 * List every type so that new backend types trigger a warning about
378 * needing to adjust this switch.
379 */
380 switch (bktype)
381 {
382 case B_INVALID:
385 case B_ARCHIVER:
386 case B_LOGGER:
387 case B_BG_WRITER:
388 case B_CHECKPOINTER:
389 case B_IO_WORKER:
390 case B_STARTUP:
391 return false;
392
393 case B_AUTOVAC_WORKER:
394 case B_BACKEND:
395 case B_BG_WORKER:
398 case B_WAL_RECEIVER:
399 case B_WAL_SENDER:
400 case B_WAL_SUMMARIZER:
401 case B_WAL_WRITER:
402 return true;
403 }
404
405 return false;
406}
407
408void
410{
411 ((PgStatShared_Backend *) header)->stats.stat_reset_timestamp = ts;
412}
PgBackendStatus * pgstat_get_beentry_by_proc_number(ProcNumber procNumber)
bool track_io_timing
Definition: bufmgr.c:147
uint32 bits32
Definition: c.h:511
uint64_t uint64
Definition: c.h:503
uint32_t uint32
Definition: c.h:502
#define MemSet(start, val, len)
Definition: c.h:991
int64 TimestampTz
Definition: timestamp.h:39
ProcNumber MyProcNumber
Definition: globals.c:91
Assert(PointerIsAligned(start, uint64))
for(;;)
#define INSTR_TIME_ADD(x, y)
Definition: instr_time.h:178
#define INSTR_TIME_GET_MICROSEC(t)
Definition: instr_time.h:194
WalUsage pgWalUsage
Definition: instrument.c:22
void WalUsageAccumDiff(WalUsage *dst, const WalUsage *add, const WalUsage *sub)
Definition: instrument.c:287
BackendType
Definition: miscadmin.h:338
@ B_WAL_SUMMARIZER
Definition: miscadmin.h:367
@ B_WAL_WRITER
Definition: miscadmin.h:368
@ B_WAL_RECEIVER
Definition: miscadmin.h:366
@ B_CHECKPOINTER
Definition: miscadmin.h:363
@ B_WAL_SENDER
Definition: miscadmin.h:347
@ B_IO_WORKER
Definition: miscadmin.h:364
@ B_LOGGER
Definition: miscadmin.h:374
@ B_STARTUP
Definition: miscadmin.h:365
@ B_BG_WORKER
Definition: miscadmin.h:346
@ B_INVALID
Definition: miscadmin.h:339
@ B_STANDALONE_BACKEND
Definition: miscadmin.h:350
@ B_BG_WRITER
Definition: miscadmin.h:362
@ B_BACKEND
Definition: miscadmin.h:342
@ B_ARCHIVER
Definition: miscadmin.h:361
@ B_AUTOVAC_LAUNCHER
Definition: miscadmin.h:344
@ B_SLOTSYNC_WORKER
Definition: miscadmin.h:348
@ B_DEAD_END_BACKEND
Definition: miscadmin.h:343
@ B_AUTOVAC_WORKER
Definition: miscadmin.h:345
BackendType MyBackendType
Definition: miscinit.c:64
void * pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
Definition: pgstat.c:946
IOObject
Definition: pgstat.h:273
#define IOOP_NUM_TYPES
Definition: pgstat.h:316
IOContext
Definition: pgstat.h:282
#define IOCONTEXT_NUM_TYPES
Definition: pgstat.h:290
IOOp
Definition: pgstat.h:302
#define IOOBJECT_NUM_TYPES
Definition: pgstat.h:279
void pgstat_create_backend(ProcNumber procnum)
static void pgstat_flush_backend_entry_wal(PgStat_EntryRef *entry_ref)
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_backend_have_pending_cb(void)
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_flush_backend(bool nowait, bits32 flags)
bool pgstat_backend_flush_cb(bool nowait)
PgStat_Backend * pgstat_fetch_stat_backend(ProcNumber procNumber)
#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:485
#define PGSTAT_KIND_BACKEND
Definition: pgstat_kind.h:32
void pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
Definition: pgstat_shmem.c:684
PgStat_EntryRef * pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, uint64 objid, bool nowait)
Definition: pgstat_shmem.c:693
#define InvalidOid
Definition: postgres_ext.h:35
#define GetNumberFromPGProc(proc)
Definition: proc.h:425
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3196
int ProcNumber
Definition: procnumber.h:24
PGPROC * AuxiliaryPidGetProc(int pid)
Definition: proc.c:1092
Definition: proc.h:163
BackendType st_backendType
PgStat_Backend stats
PgStat_PendingIO pending_io
Definition: pgstat.h:504
PgStat_WalCounters wal_counters
Definition: pgstat.h:492
PgStat_BktypeIO io_stats
Definition: pgstat.h:491
PgStat_Counter times[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:326
uint64 bytes[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:324
PgStat_Counter counts[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:325
PgStatShared_Common * shared_stats
PgStat_Counter counts[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:332
uint64 bytes[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:331
instr_time pending_times[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:333
int64 wal_records
Definition: instrument.h:53
bool track_wal_io_timing
Definition: xlog.c:137