PostgreSQL Source Code git master
pgstat_slru.c
Go to the documentation of this file.
1/* -------------------------------------------------------------------------
2 *
3 * pgstat_slru.c
4 * Implementation of SLRU statistics.
5 *
6 * This file contains the implementation of SLRU 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 * Copyright (c) 2001-2025, PostgreSQL Global Development Group
12 *
13 * IDENTIFICATION
14 * src/backend/utils/activity/pgstat_slru.c
15 * -------------------------------------------------------------------------
16 */
17
18#include "postgres.h"
19
21#include "utils/timestamp.h"
22
23
24static inline PgStat_SLRUStats *get_slru_entry(int slru_idx);
26
27
28/*
29 * SLRU statistics counts waiting to be flushed out. We assume this variable
30 * inits to zeroes. Entries are one-to-one with slru_names[]. Changes of
31 * SLRU counters are reported within critical sections so we use static memory
32 * in order to avoid memory allocation.
33 */
35static bool have_slrustats = false;
36
37
38/*
39 * Reset counters for a single SLRU.
40 *
41 * Permission checking for this function is managed through the normal
42 * GRANT system.
43 */
44void
46{
48
49 Assert(name != NULL);
50
52}
53
54/*
55 * SLRU statistics count accumulation functions --- called from slru.c
56 */
57
58#define PGSTAT_COUNT_SLRU(stat) \
59void \
60CppConcat(pgstat_count_slru_,stat)(int slru_idx) \
61{ \
62 get_slru_entry(slru_idx)->stat += 1; \
63}
64
65/* pgstat_count_slru_blocks_zeroed */
66PGSTAT_COUNT_SLRU(blocks_zeroed)
67
68/* pgstat_count_slru_blocks_hit */
69PGSTAT_COUNT_SLRU(blocks_hit)
70
71/* pgstat_count_slru_blocks_exists */
72PGSTAT_COUNT_SLRU(blocks_exists)
73
74/* pgstat_count_slru_blocks_read */
75PGSTAT_COUNT_SLRU(blocks_read)
76
77/* pgstat_count_slru_blocks_written */
79
80/* pgstat_count_slru_flush */
82
83/* pgstat_count_slru_truncate */
84PGSTAT_COUNT_SLRU(truncate)
85
86/*
87 * Support function for the SQL-callable pgstat* functions. Returns
88 * a pointer to the slru statistics struct.
89 */
92{
94
96}
97
98/*
99 * Returns SLRU name for an index. The index may be above SLRU_NUM_ELEMENTS,
100 * in which case this returns NULL. This allows writing code that does not
101 * know the number of entries in advance.
102 */
103const char *
105{
106 if (slru_idx < 0 || slru_idx >= SLRU_NUM_ELEMENTS)
107 return NULL;
108
109 return slru_names[slru_idx];
110}
111
112/*
113 * Determine index of entry for a SLRU with a given name. If there's no exact
114 * match, returns index of the last "other" entry used for SLRUs defined in
115 * external projects.
116 */
117int
119{
120 int i;
121
122 for (i = 0; i < SLRU_NUM_ELEMENTS; i++)
123 {
124 if (strcmp(slru_names[i], name) == 0)
125 return i;
126 }
127
128 /* return index of the last entry (which is the "other" one) */
129 return (SLRU_NUM_ELEMENTS - 1);
130}
131
132/*
133 * Flush out locally pending SLRU stats entries
134 *
135 * If nowait is true, this function returns false on lock failure. Otherwise
136 * this function always returns true.
137 *
138 * If nowait is true, this function returns true if the lock could not be
139 * acquired. Otherwise return false.
140 */
141bool
143{
144 PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
145 int i;
146
147 if (!have_slrustats)
148 return false;
149
150 if (!nowait)
151 LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
152 else if (!LWLockConditionalAcquire(&stats_shmem->lock, LW_EXCLUSIVE))
153 return true;
154
155 for (i = 0; i < SLRU_NUM_ELEMENTS; i++)
156 {
157 PgStat_SLRUStats *sharedent = &stats_shmem->stats[i];
158 PgStat_SLRUStats *pendingent = &pending_SLRUStats[i];
159
160#define SLRU_ACC(fld) sharedent->fld += pendingent->fld
161 SLRU_ACC(blocks_zeroed);
162 SLRU_ACC(blocks_hit);
163 SLRU_ACC(blocks_read);
165 SLRU_ACC(blocks_exists);
166 SLRU_ACC(flush);
167 SLRU_ACC(truncate);
168#undef SLRU_ACC
169 }
170
171 /* done, clear the pending entry */
173
174 LWLockRelease(&stats_shmem->lock);
175
176 have_slrustats = false;
177
178 return false;
179}
180
181void
183{
184 PgStatShared_SLRU *stats_shmem = (PgStatShared_SLRU *) stats;
185
186 LWLockInitialize(&stats_shmem->lock, LWTRANCHE_PGSTATS_DATA);
187}
188
189void
191{
192 for (int i = 0; i < SLRU_NUM_ELEMENTS; i++)
194}
195
196void
198{
199 PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
200
201 LWLockAcquire(&stats_shmem->lock, LW_SHARED);
202
203 memcpy(pgStatLocal.snapshot.slru, &stats_shmem->stats,
204 sizeof(stats_shmem->stats));
205
206 LWLockRelease(&stats_shmem->lock);
207}
208
209/*
210 * Returns pointer to entry with counters for given SLRU (based on the name
211 * stored in SlruCtl as lwlock tranche name).
212 */
213static inline PgStat_SLRUStats *
214get_slru_entry(int slru_idx)
215{
217
218 /*
219 * The postmaster should never register any SLRU statistics counts; if it
220 * did, the counts would be duplicated into child processes via fork().
221 */
223
224 Assert((slru_idx >= 0) && (slru_idx < SLRU_NUM_ELEMENTS));
225
226 have_slrustats = true;
227 pgstat_report_fixed = true;
228
229 return &pending_SLRUStats[slru_idx];
230}
231
232static void
234{
235 PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
236
237 LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
238
239 memset(&stats_shmem->stats[index], 0, sizeof(PgStat_SLRUStats));
240 stats_shmem->stats[index].stat_reset_timestamp = ts;
241
242 LWLockRelease(&stats_shmem->lock);
243}
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1645
#define MemSet(start, val, len)
Definition: c.h:1023
int64 TimestampTz
Definition: timestamp.h:39
bool IsUnderPostmaster
Definition: globals.c:120
bool IsPostmasterEnvironment
Definition: globals.c:119
Assert(PointerIsAligned(start, uint64))
int i
Definition: isn.c:77
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1174
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1894
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:698
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1345
@ LW_SHARED
Definition: lwlock.h:113
@ LW_EXCLUSIVE
Definition: lwlock.h:112
static int64 blocks_written
Definition: pg_checksums.c:39
void pgstat_snapshot_fixed(PgStat_Kind kind)
Definition: pgstat.c:1060
bool pgstat_report_fixed
Definition: pgstat.c:218
PgStat_LocalState pgStatLocal
Definition: pgstat.c:212
static const char *const slru_names[]
#define pgstat_assert_is_up()
#define SLRU_NUM_ELEMENTS
#define PGSTAT_KIND_SLRU
Definition: pgstat_kind.h:39
static bool have_slrustats
Definition: pgstat_slru.c:35
void pgstat_slru_snapshot_cb(void)
Definition: pgstat_slru.c:197
static PgStat_SLRUStats pending_SLRUStats[SLRU_NUM_ELEMENTS]
Definition: pgstat_slru.c:34
int pgstat_get_slru_index(const char *name)
Definition: pgstat_slru.c:118
PgStat_SLRUStats * pgstat_fetch_slru(void)
Definition: pgstat_slru.c:91
#define PGSTAT_COUNT_SLRU(stat)
Definition: pgstat_slru.c:58
bool pgstat_slru_flush_cb(bool nowait)
Definition: pgstat_slru.c:142
#define SLRU_ACC(fld)
static void pgstat_reset_slru_counter_internal(int index, TimestampTz ts)
Definition: pgstat_slru.c:233
const char * pgstat_get_slru_name(int slru_idx)
Definition: pgstat_slru.c:104
void pgstat_reset_slru(const char *name)
Definition: pgstat_slru.c:45
void pgstat_slru_reset_all_cb(TimestampTz ts)
Definition: pgstat_slru.c:190
void pgstat_slru_init_shmem_cb(void *stats)
Definition: pgstat_slru.c:182
static PgStat_SLRUStats * get_slru_entry(int slru_idx)
Definition: pgstat_slru.c:214
PgStat_SLRUStats stats[SLRU_NUM_ELEMENTS]
PgStat_Snapshot snapshot
PgStat_ShmemControl * shmem
TimestampTz stat_reset_timestamp
Definition: pgstat.h:413
PgStatShared_SLRU slru
PgStat_SLRUStats slru[SLRU_NUM_ELEMENTS]
Definition: type.h:96
const char * name