PostgreSQL Source Code git master
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 "storage/bufmgr.h"
28#include "utils/memutils.h"
30
31/*
32 * Backend statistics counts waiting to be flushed out. These counters may be
33 * reported within critical sections so we use static memory in order to avoid
34 * memory allocation.
35 */
37
38/*
39 * Utility routines to report I/O stats for backends, kept here to avoid
40 * exposing PendingBackendStats to the outside world.
41 */
42void
44 IOOp io_op, instr_time io_time)
45{
47
49 return;
50
51 Assert(pgstat_tracks_io_op(MyBackendType, io_object, io_context, io_op));
52
53 INSTR_TIME_ADD(PendingBackendStats.pending_io.pending_times[io_object][io_context][io_op],
54 io_time);
55}
56
57void
59 IOOp io_op, uint32 cnt, uint64 bytes)
60{
62 return;
63
64 Assert(pgstat_tracks_io_op(MyBackendType, io_object, io_context, io_op));
65
66 PendingBackendStats.pending_io.counts[io_object][io_context][io_op] += cnt;
67 PendingBackendStats.pending_io.bytes[io_object][io_context][io_op] += bytes;
68}
69
70/*
71 * Returns statistics of a backend by proc number.
72 */
75{
76 PgStat_Backend *backend_entry;
77
79 InvalidOid, procNumber);
80
81 return backend_entry;
82}
83
84/*
85 * Flush out locally pending backend IO statistics. Locking is managed
86 * by the caller.
87 */
88static void
90{
91 PgStatShared_Backend *shbackendent;
92 PgStat_BktypeIO *bktype_shstats;
93 PgStat_PendingIO pending_io;
94
95 /*
96 * This function can be called even if nothing at all has happened for IO
97 * statistics. In this case, avoid unnecessarily modifying the stats
98 * entry.
99 */
101 sizeof(struct PgStat_PendingIO)))
102 return;
103
104 shbackendent = (PgStatShared_Backend *) entry_ref->shared_stats;
105 bktype_shstats = &shbackendent->stats.io_stats;
106 pending_io = PendingBackendStats.pending_io;
107
108 for (int io_object = 0; io_object < IOOBJECT_NUM_TYPES; io_object++)
109 {
110 for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++)
111 {
112 for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++)
113 {
114 instr_time time;
115
116 bktype_shstats->counts[io_object][io_context][io_op] +=
117 pending_io.counts[io_object][io_context][io_op];
118 bktype_shstats->bytes[io_object][io_context][io_op] +=
119 pending_io.bytes[io_object][io_context][io_op];
120 time = pending_io.pending_times[io_object][io_context][io_op];
121
122 bktype_shstats->times[io_object][io_context][io_op] +=
124 }
125 }
126 }
127
128 /*
129 * Clear out the statistics buffer, so it can be re-used.
130 */
132}
133
134/*
135 * Flush out locally pending backend statistics
136 *
137 * "flags" parameter controls which statistics to flush. Returns true
138 * if some statistics could not be flushed due to lock contention.
139 */
140bool
141pgstat_flush_backend(bool nowait, bits32 flags)
142{
143 PgStat_EntryRef *entry_ref;
144
146 return false;
147
149 sizeof(struct PgStat_BackendPending)))
150 return false;
151
153 MyProcNumber, nowait);
154 if (!entry_ref)
155 return true;
156
157 /* Flush requested statistics */
158 if (flags & PGSTAT_BACKEND_FLUSH_IO)
160
161 pgstat_unlock_entry(entry_ref);
162
163 return false;
164}
165
166/*
167 * Check if there are any backend stats waiting for flush.
168 */
169bool
171{
173 sizeof(struct PgStat_BackendPending)));
174}
175
176/*
177 * Callback to flush out locally pending backend statistics.
178 *
179 * If some stats could not be flushed due to lock contention, return true.
180 */
181bool
183{
185}
186
187/*
188 * Create backend statistics entry for proc number.
189 */
190void
192{
193 PgStat_EntryRef *entry_ref;
194 PgStatShared_Backend *shstatent;
195
197 MyProcNumber, false);
198 shstatent = (PgStatShared_Backend *) entry_ref->shared_stats;
199
200 /*
201 * NB: need to accept that there might be stats from an older backend,
202 * e.g. if we previously used this proc number.
203 */
204 memset(&shstatent->stats, 0, sizeof(shstatent->stats));
205 pgstat_unlock_entry(entry_ref);
206
208}
209
210/*
211 * Backend statistics are not collected for all BackendTypes.
212 *
213 * The following BackendTypes do not participate in the backend stats
214 * subsystem:
215 * - The same and for the same reasons as in pgstat_tracks_io_bktype().
216 * - B_BG_WRITER, B_CHECKPOINTER, B_STARTUP and B_AUTOVAC_LAUNCHER because their
217 * I/O stats are already visible in pg_stat_io and there is only one of those.
218 *
219 * Function returns true if BackendType participates in the backend stats
220 * subsystem and false if it does not.
221 *
222 * When adding a new BackendType, also consider adding relevant restrictions to
223 * pgstat_tracks_io_object() and pgstat_tracks_io_op().
224 */
225bool
227{
228 /*
229 * List every type so that new backend types trigger a warning about
230 * needing to adjust this switch.
231 */
232 switch (bktype)
233 {
234 case B_INVALID:
237 case B_ARCHIVER:
238 case B_LOGGER:
239 case B_BG_WRITER:
240 case B_CHECKPOINTER:
241 case B_STARTUP:
242 return false;
243
244 case B_AUTOVAC_WORKER:
245 case B_BACKEND:
246 case B_BG_WORKER:
249 case B_WAL_RECEIVER:
250 case B_WAL_SENDER:
251 case B_WAL_SUMMARIZER:
252 case B_WAL_WRITER:
253 return true;
254 }
255
256 return false;
257}
258
259void
261{
262 ((PgStatShared_Backend *) header)->stats.stat_reset_timestamp = ts;
263}
bool track_io_timing
Definition: bufmgr.c:143
#define Assert(condition)
Definition: c.h:815
uint32 bits32
Definition: c.h:497
uint64_t uint64
Definition: c.h:489
uint32_t uint32
Definition: c.h:488
#define MemSet(start, val, len)
Definition: c.h:977
int64 TimestampTz
Definition: timestamp.h:39
ProcNumber MyProcNumber
Definition: globals.c:89
for(;;)
#define INSTR_TIME_ADD(x, y)
Definition: instr_time.h:178
#define INSTR_TIME_GET_MICROSEC(t)
Definition: instr_time.h:194
static bool pg_memory_is_all_zeros(const void *ptr, size_t len)
Definition: memutils.h:219
BackendType
Definition: miscadmin.h:337
@ B_WAL_SUMMARIZER
Definition: miscadmin.h:365
@ B_WAL_WRITER
Definition: miscadmin.h:366
@ B_WAL_RECEIVER
Definition: miscadmin.h:364
@ B_CHECKPOINTER
Definition: miscadmin.h:362
@ B_WAL_SENDER
Definition: miscadmin.h:346
@ B_LOGGER
Definition: miscadmin.h:372
@ B_STARTUP
Definition: miscadmin.h:363
@ B_BG_WORKER
Definition: miscadmin.h:345
@ B_INVALID
Definition: miscadmin.h:338
@ B_STANDALONE_BACKEND
Definition: miscadmin.h:349
@ B_BG_WRITER
Definition: miscadmin.h:361
@ B_BACKEND
Definition: miscadmin.h:341
@ B_ARCHIVER
Definition: miscadmin.h:360
@ B_AUTOVAC_LAUNCHER
Definition: miscadmin.h:343
@ B_SLOTSYNC_WORKER
Definition: miscadmin.h:347
@ B_DEAD_END_BACKEND
Definition: miscadmin.h:342
@ B_AUTOVAC_WORKER
Definition: miscadmin.h:344
BackendType MyBackendType
Definition: miscinit.c:64
void * pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
Definition: pgstat.c:950
IOObject
Definition: pgstat.h:274
#define IOOP_NUM_TYPES
Definition: pgstat.h:317
IOContext
Definition: pgstat.h:283
#define IOCONTEXT_NUM_TYPES
Definition: pgstat.h:291
IOOp
Definition: pgstat.h:303
#define IOOBJECT_NUM_TYPES
Definition: pgstat.h:280
void pgstat_create_backend(ProcNumber procnum)
static PgStat_BackendPending PendingBackendStats
bool pgstat_tracks_backend_bktype(BackendType bktype)
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)
bool pgstat_backend_have_pending_cb(void)
void pgstat_backend_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)
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
bool pgstat_tracks_io_op(BackendType bktype, IOObject io_object, IOContext io_context, IOOp io_op)
Definition: pgstat_io.c:473
#define PGSTAT_KIND_BACKEND
Definition: pgstat_kind.h:32
void pgstat_unlock_entry(PgStat_EntryRef *entry_ref)
Definition: pgstat_shmem.c:675
PgStat_EntryRef * pgstat_get_entry_ref_locked(PgStat_Kind kind, Oid dboid, uint64 objid, bool nowait)
Definition: pgstat_shmem.c:684
#define InvalidOid
Definition: postgres_ext.h:37
int ProcNumber
Definition: procnumber.h:24
PgStat_Backend stats
PgStat_PendingIO pending_io
Definition: pgstat.h:358
PgStat_BktypeIO io_stats
Definition: pgstat.h:346
PgStat_Counter times[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:327
uint64 bytes[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:325
PgStat_Counter counts[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:326
PgStatShared_Common * shared_stats
PgStat_Counter counts[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:333
uint64 bytes[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:332
instr_time pending_times[IOOBJECT_NUM_TYPES][IOCONTEXT_NUM_TYPES][IOOP_NUM_TYPES]
Definition: pgstat.h:334