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-2024, PostgreSQL Global Development Group
12  *
13  * IDENTIFICATION
14  * src/backend/utils/activity/pgstat_slru.c
15  * -------------------------------------------------------------------------
16  */
17 
18 #include "postgres.h"
19 
20 #include "utils/pgstat_internal.h"
21 #include "utils/timestamp.h"
22 
23 
24 static 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  */
35 static 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  */
44 void
45 pgstat_reset_slru(const char *name)
46 {
48 
49  Assert(name != NULL);
50 
52 }
53 
54 /*
55  * SLRU statistics count accumulation functions --- called from slru.c
56  */
57 
58 void
60 {
61  get_slru_entry(slru_idx)->blocks_zeroed += 1;
62 }
63 
64 void
66 {
67  get_slru_entry(slru_idx)->blocks_hit += 1;
68 }
69 
70 void
72 {
73  get_slru_entry(slru_idx)->blocks_exists += 1;
74 }
75 
76 void
78 {
79  get_slru_entry(slru_idx)->blocks_read += 1;
80 }
81 
82 void
84 {
85  get_slru_entry(slru_idx)->blocks_written += 1;
86 }
87 
88 void
90 {
91  get_slru_entry(slru_idx)->flush += 1;
92 }
93 
94 void
96 {
97  get_slru_entry(slru_idx)->truncate += 1;
98 }
99 
100 /*
101  * Support function for the SQL-callable pgstat* functions. Returns
102  * a pointer to the slru statistics struct.
103  */
106 {
108 
109  return pgStatLocal.snapshot.slru;
110 }
111 
112 /*
113  * Returns SLRU name for an index. The index may be above SLRU_NUM_ELEMENTS,
114  * in which case this returns NULL. This allows writing code that does not
115  * know the number of entries in advance.
116  */
117 const char *
118 pgstat_get_slru_name(int slru_idx)
119 {
120  if (slru_idx < 0 || slru_idx >= SLRU_NUM_ELEMENTS)
121  return NULL;
122 
123  return slru_names[slru_idx];
124 }
125 
126 /*
127  * Determine index of entry for a SLRU with a given name. If there's no exact
128  * match, returns index of the last "other" entry used for SLRUs defined in
129  * external projects.
130  */
131 int
133 {
134  int i;
135 
136  for (i = 0; i < SLRU_NUM_ELEMENTS; i++)
137  {
138  if (strcmp(slru_names[i], name) == 0)
139  return i;
140  }
141 
142  /* return index of the last entry (which is the "other" one) */
143  return (SLRU_NUM_ELEMENTS - 1);
144 }
145 
146 /*
147  * Check if there are any SLRU stats entries waiting for flush.
148  */
149 bool
151 {
152  return have_slrustats;
153 }
154 
155 /*
156  * Flush out locally pending SLRU stats entries
157  *
158  * If nowait is true, this function returns false on lock failure. Otherwise
159  * this function always returns true.
160  *
161  * If nowait is true, this function returns true if the lock could not be
162  * acquired. Otherwise return false.
163  */
164 bool
166 {
167  PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
168  int i;
169 
170  if (!have_slrustats)
171  return false;
172 
173  if (!nowait)
174  LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
175  else if (!LWLockConditionalAcquire(&stats_shmem->lock, LW_EXCLUSIVE))
176  return true;
177 
178  for (i = 0; i < SLRU_NUM_ELEMENTS; i++)
179  {
180  PgStat_SLRUStats *sharedent = &stats_shmem->stats[i];
181  PgStat_SLRUStats *pendingent = &pending_SLRUStats[i];
182 
183 #define SLRU_ACC(fld) sharedent->fld += pendingent->fld
184  SLRU_ACC(blocks_zeroed);
185  SLRU_ACC(blocks_hit);
186  SLRU_ACC(blocks_read);
188  SLRU_ACC(blocks_exists);
189  SLRU_ACC(flush);
190  SLRU_ACC(truncate);
191 #undef SLRU_ACC
192  }
193 
194  /* done, clear the pending entry */
196 
197  LWLockRelease(&stats_shmem->lock);
198 
199  have_slrustats = false;
200 
201  return false;
202 }
203 
204 void
206 {
207  PgStatShared_SLRU *stats_shmem = (PgStatShared_SLRU *) stats;
208 
210 }
211 
212 void
214 {
215  for (int i = 0; i < SLRU_NUM_ELEMENTS; i++)
217 }
218 
219 void
221 {
222  PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
223 
224  LWLockAcquire(&stats_shmem->lock, LW_SHARED);
225 
226  memcpy(pgStatLocal.snapshot.slru, &stats_shmem->stats,
227  sizeof(stats_shmem->stats));
228 
229  LWLockRelease(&stats_shmem->lock);
230 }
231 
232 /*
233  * Returns pointer to entry with counters for given SLRU (based on the name
234  * stored in SlruCtl as lwlock tranche name).
235  */
236 static inline PgStat_SLRUStats *
237 get_slru_entry(int slru_idx)
238 {
240 
241  /*
242  * The postmaster should never register any SLRU statistics counts; if it
243  * did, the counts would be duplicated into child processes via fork().
244  */
246 
247  Assert((slru_idx >= 0) && (slru_idx < SLRU_NUM_ELEMENTS));
248 
249  have_slrustats = true;
250 
251  return &pending_SLRUStats[slru_idx];
252 }
253 
254 static void
256 {
257  PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
258 
259  LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
260 
261  memset(&stats_shmem->stats[index], 0, sizeof(PgStat_SLRUStats));
262  stats_shmem->stats[index].stat_reset_timestamp = ts;
263 
264  LWLockRelease(&stats_shmem->lock);
265 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1644
#define Assert(condition)
Definition: c.h:849
#define MemSet(start, val, len)
Definition: c.h:1011
int64 TimestampTz
Definition: timestamp.h:39
bool IsUnderPostmaster
Definition: globals.c:119
bool IsPostmasterEnvironment
Definition: globals.c:118
int i
Definition: isn.c:73
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:707
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1339
@ LWTRANCHE_PGSTATS_DATA
Definition: lwlock.h:205
@ LW_SHARED
Definition: lwlock.h:115
@ LW_EXCLUSIVE
Definition: lwlock.h:114
static int64 blocks_written
Definition: pg_checksums.c:39
void pgstat_snapshot_fixed(PgStat_Kind kind)
Definition: pgstat.c:1054
PgStat_LocalState pgStatLocal
Definition: pgstat.c:212
#define PGSTAT_KIND_SLRU
Definition: pgstat.h:58
static const char *const slru_names[]
#define pgstat_assert_is_up()
#define SLRU_NUM_ELEMENTS
static bool have_slrustats
Definition: pgstat_slru.c:35
void pgstat_slru_snapshot_cb(void)
Definition: pgstat_slru.c:220
void pgstat_count_slru_page_exists(int slru_idx)
Definition: pgstat_slru.c:71
void pgstat_count_slru_page_read(int slru_idx)
Definition: pgstat_slru.c:77
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:132
void pgstat_count_slru_page_hit(int slru_idx)
Definition: pgstat_slru.c:65
void pgstat_count_slru_page_zeroed(int slru_idx)
Definition: pgstat_slru.c:59
void pgstat_count_slru_truncate(int slru_idx)
Definition: pgstat_slru.c:95
bool pgstat_slru_flush_cb(bool nowait)
Definition: pgstat_slru.c:165
#define SLRU_ACC(fld)
static void pgstat_reset_slru_counter_internal(int index, TimestampTz ts)
Definition: pgstat_slru.c:255
void pgstat_count_slru_page_written(int slru_idx)
Definition: pgstat_slru.c:83
void pgstat_reset_slru(const char *name)
Definition: pgstat_slru.c:45
PgStat_SLRUStats * pgstat_fetch_slru(void)
Definition: pgstat_slru.c:105
const char * pgstat_get_slru_name(int slru_idx)
Definition: pgstat_slru.c:118
void pgstat_slru_reset_all_cb(TimestampTz ts)
Definition: pgstat_slru.c:213
void pgstat_count_slru_flush(int slru_idx)
Definition: pgstat_slru.c:89
void pgstat_slru_init_shmem_cb(void *stats)
Definition: pgstat_slru.c:205
bool pgstat_slru_have_pending_cb(void)
Definition: pgstat_slru.c:150
static PgStat_SLRUStats * get_slru_entry(int slru_idx)
Definition: pgstat_slru.c:237
PgStat_SLRUStats stats[SLRU_NUM_ELEMENTS]
PgStat_Snapshot snapshot
PgStat_ShmemControl * shmem
PgStat_Counter blocks_read
Definition: pgstat.h:418
PgStat_Counter blocks_exists
Definition: pgstat.h:420
TimestampTz stat_reset_timestamp
Definition: pgstat.h:423
PgStat_Counter blocks_zeroed
Definition: pgstat.h:416
PgStat_Counter blocks_written
Definition: pgstat.h:419
PgStat_Counter blocks_hit
Definition: pgstat.h:417
PgStat_Counter truncate
Definition: pgstat.h:422
PgStat_Counter flush
Definition: pgstat.h:421
PgStatShared_SLRU slru
PgStat_SLRUStats slru[SLRU_NUM_ELEMENTS]
Definition: type.h:95
const char * name