Line data Source code
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. 15 : * 16 : * Copyright (c) 2001-2025, PostgreSQL Global Development Group 17 : * 18 : * IDENTIFICATION 19 : * src/backend/utils/activity/pgstat_backend.c 20 : * ------------------------------------------------------------------------- 21 : */ 22 : 23 : #include "postgres.h" 24 : 25 : #include "utils/pgstat_internal.h" 26 : 27 : /* 28 : * Returns statistics of a backend by proc number. 29 : */ 30 : PgStat_Backend * 31 42 : pgstat_fetch_stat_backend(ProcNumber procNumber) 32 : { 33 : PgStat_Backend *backend_entry; 34 : 35 42 : backend_entry = (PgStat_Backend *) pgstat_fetch_entry(PGSTAT_KIND_BACKEND, 36 : InvalidOid, procNumber); 37 : 38 42 : return backend_entry; 39 : } 40 : 41 : /* 42 : * Flush out locally pending backend IO statistics. Locking is managed 43 : * by the caller. 44 : */ 45 : static void 46 186946 : pgstat_flush_backend_entry_io(PgStat_EntryRef *entry_ref) 47 : { 48 : PgStatShared_Backend *shbackendent; 49 : PgStat_BackendPending *pendingent; 50 : PgStat_BktypeIO *bktype_shstats; 51 : PgStat_PendingIO *pending_io; 52 : 53 186946 : shbackendent = (PgStatShared_Backend *) entry_ref->shared_stats; 54 186946 : pendingent = (PgStat_BackendPending *) entry_ref->pending; 55 186946 : bktype_shstats = &shbackendent->stats.io_stats; 56 186946 : pending_io = &pendingent->pending_io; 57 : 58 560838 : for (int io_object = 0; io_object < IOOBJECT_NUM_TYPES; io_object++) 59 : { 60 1869460 : for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++) 61 : { 62 13460112 : for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++) 63 : { 64 : instr_time time; 65 : 66 11964544 : bktype_shstats->counts[io_object][io_context][io_op] += 67 11964544 : pending_io->counts[io_object][io_context][io_op]; 68 11964544 : bktype_shstats->bytes[io_object][io_context][io_op] += 69 11964544 : pending_io->bytes[io_object][io_context][io_op]; 70 : 71 11964544 : time = pending_io->pending_times[io_object][io_context][io_op]; 72 : 73 11964544 : bktype_shstats->times[io_object][io_context][io_op] += 74 11964544 : INSTR_TIME_GET_MICROSEC(time); 75 : } 76 : } 77 : } 78 186946 : } 79 : 80 : /* 81 : * Wrapper routine to flush backend statistics. 82 : */ 83 : static bool 84 186946 : pgstat_flush_backend_entry(PgStat_EntryRef *entry_ref, bool nowait, 85 : bits32 flags) 86 : { 87 186946 : if (!pgstat_tracks_backend_bktype(MyBackendType)) 88 0 : return false; 89 : 90 186946 : if (!pgstat_lock_entry(entry_ref, nowait)) 91 0 : return false; 92 : 93 : /* Flush requested statistics */ 94 186946 : if (flags & PGSTAT_BACKEND_FLUSH_IO) 95 186946 : pgstat_flush_backend_entry_io(entry_ref); 96 : 97 186946 : pgstat_unlock_entry(entry_ref); 98 : 99 186946 : return true; 100 : } 101 : 102 : /* 103 : * Callback to flush out locally pending backend statistics. 104 : * 105 : * If no stats have been recorded, this function returns false. 106 : */ 107 : bool 108 59532 : pgstat_backend_flush_cb(PgStat_EntryRef *entry_ref, bool nowait) 109 : { 110 59532 : return pgstat_flush_backend_entry(entry_ref, nowait, PGSTAT_BACKEND_FLUSH_ALL); 111 : } 112 : 113 : /* 114 : * Flush out locally pending backend statistics 115 : * 116 : * "flags" parameter controls which statistics to flush. 117 : */ 118 : void 119 127414 : pgstat_flush_backend(bool nowait, bits32 flags) 120 : { 121 : PgStat_EntryRef *entry_ref; 122 : 123 127414 : if (!pgstat_tracks_backend_bktype(MyBackendType)) 124 0 : return; 125 : 126 127414 : entry_ref = pgstat_get_entry_ref(PGSTAT_KIND_BACKEND, InvalidOid, 127 : MyProcNumber, false, NULL); 128 127414 : (void) pgstat_flush_backend_entry(entry_ref, nowait, flags); 129 : } 130 : 131 : /* 132 : * Create backend statistics entry for proc number. 133 : */ 134 : void 135 31812 : pgstat_create_backend(ProcNumber procnum) 136 : { 137 : PgStat_EntryRef *entry_ref; 138 : PgStatShared_Backend *shstatent; 139 : 140 31812 : entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_BACKEND, InvalidOid, 141 : procnum, NULL); 142 : 143 31812 : shstatent = (PgStatShared_Backend *) entry_ref->shared_stats; 144 : 145 : /* 146 : * NB: need to accept that there might be stats from an older backend, 147 : * e.g. if we previously used this proc number. 148 : */ 149 31812 : memset(&shstatent->stats, 0, sizeof(shstatent->stats)); 150 31812 : } 151 : 152 : /* 153 : * Find or create a local PgStat_BackendPending entry for proc number. 154 : */ 155 : PgStat_BackendPending * 156 102470702 : pgstat_prep_backend_pending(ProcNumber procnum) 157 : { 158 : PgStat_EntryRef *entry_ref; 159 : 160 102470702 : entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_BACKEND, InvalidOid, 161 : procnum, NULL); 162 : 163 102470702 : return entry_ref->pending; 164 : } 165 : 166 : /* 167 : * Backend statistics are not collected for all BackendTypes. 168 : * 169 : * The following BackendTypes do not participate in the backend stats 170 : * subsystem: 171 : * - The same and for the same reasons as in pgstat_tracks_io_bktype(). 172 : * - B_BG_WRITER, B_CHECKPOINTER, B_STARTUP and B_AUTOVAC_LAUNCHER because their 173 : * I/O stats are already visible in pg_stat_io and there is only one of those. 174 : * 175 : * Function returns true if BackendType participates in the backend stats 176 : * subsystem and false if it does not. 177 : * 178 : * When adding a new BackendType, also consider adding relevant restrictions to 179 : * pgstat_tracks_io_object() and pgstat_tracks_io_op(). 180 : */ 181 : bool 182 114049658 : pgstat_tracks_backend_bktype(BackendType bktype) 183 : { 184 : /* 185 : * List every type so that new backend types trigger a warning about 186 : * needing to adjust this switch. 187 : */ 188 114049658 : switch (bktype) 189 : { 190 11232784 : case B_INVALID: 191 : case B_AUTOVAC_LAUNCHER: 192 : case B_DEAD_END_BACKEND: 193 : case B_ARCHIVER: 194 : case B_LOGGER: 195 : case B_WAL_RECEIVER: 196 : case B_WAL_WRITER: 197 : case B_WAL_SUMMARIZER: 198 : case B_BG_WRITER: 199 : case B_CHECKPOINTER: 200 : case B_STARTUP: 201 11232784 : return false; 202 : 203 102816874 : case B_AUTOVAC_WORKER: 204 : case B_BACKEND: 205 : case B_BG_WORKER: 206 : case B_STANDALONE_BACKEND: 207 : case B_SLOTSYNC_WORKER: 208 : case B_WAL_SENDER: 209 102816874 : return true; 210 : } 211 : 212 0 : return false; 213 : } 214 : 215 : void 216 6 : pgstat_backend_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts) 217 : { 218 6 : ((PgStatShared_Backend *) header)->stats.stat_reset_timestamp = ts; 219 6 : }