Age Owner Branch data TLA Line data Source code
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);
25 : : static void pgstat_reset_slru_counter_internal(int index, TimestampTz ts);
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 : : */
34 : : static PgStat_SLRUStats pending_SLRUStats[SLRU_NUM_ELEMENTS];
35 : : 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
739 andres@anarazel.de 45 :CBC 3 : pgstat_reset_slru(const char *name)
46 : : {
47 : 3 : TimestampTz ts = GetCurrentTimestamp();
48 : :
534 peter@eisentraut.org 49 [ - + ]: 3 : Assert(name != NULL);
50 : :
739 andres@anarazel.de 51 : 3 : pgstat_reset_slru_counter_internal(pgstat_get_slru_index(name), ts);
755 52 : 3 : }
53 : :
54 : : /*
55 : : * SLRU statistics count accumulation functions --- called from slru.c
56 : : */
57 : :
58 : : void
59 : 7339405 : pgstat_count_slru_page_zeroed(int slru_idx)
60 : : {
739 61 : 7339405 : get_slru_entry(slru_idx)->blocks_zeroed += 1;
755 62 : 7339405 : }
63 : :
64 : : void
65 : 789856 : pgstat_count_slru_page_hit(int slru_idx)
66 : : {
739 67 : 789856 : get_slru_entry(slru_idx)->blocks_hit += 1;
755 68 : 789856 : }
69 : :
70 : : void
71 : 70 : pgstat_count_slru_page_exists(int slru_idx)
72 : : {
739 73 : 70 : get_slru_entry(slru_idx)->blocks_exists += 1;
755 74 : 70 : }
75 : :
76 : : void
77 : 1690 : pgstat_count_slru_page_read(int slru_idx)
78 : : {
739 79 : 1690 : get_slru_entry(slru_idx)->blocks_read += 1;
755 80 : 1690 : }
81 : :
82 : : void
83 : 7340843 : pgstat_count_slru_page_written(int slru_idx)
84 : : {
739 85 : 7340843 : get_slru_entry(slru_idx)->blocks_written += 1;
755 86 : 7340843 : }
87 : :
88 : : void
89 : 5789 : pgstat_count_slru_flush(int slru_idx)
90 : : {
739 91 : 5789 : get_slru_entry(slru_idx)->flush += 1;
755 92 : 5789 : }
93 : :
94 : : void
95 : 1092 : pgstat_count_slru_truncate(int slru_idx)
96 : : {
739 97 : 1092 : get_slru_entry(slru_idx)->truncate += 1;
98 : 1092 : }
99 : :
100 : : /*
101 : : * Support function for the SQL-callable pgstat* functions. Returns
102 : : * a pointer to the slru statistics struct.
103 : : */
104 : : PgStat_SLRUStats *
105 : 62 : pgstat_fetch_slru(void)
106 : : {
107 : 62 : pgstat_snapshot_fixed(PGSTAT_KIND_SLRU);
108 : :
109 : 62 : 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 : 558 : pgstat_get_slru_name(int slru_idx)
119 : : {
755 120 [ + - + + ]: 558 : if (slru_idx < 0 || slru_idx >= SLRU_NUM_ELEMENTS)
121 : 62 : return NULL;
122 : :
123 : 496 : 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
739 132 : 6290 : pgstat_get_slru_index(const char *name)
133 : : {
134 : : int i;
135 : :
755 136 [ + + ]: 25156 : for (i = 0; i < SLRU_NUM_ELEMENTS; i++)
137 : : {
138 [ + + ]: 25155 : if (strcmp(slru_names[i], name) == 0)
139 : 6289 : return i;
140 : : }
141 : :
142 : : /* return index of the last entry (which is the "other" one) */
143 : 1 : return (SLRU_NUM_ELEMENTS - 1);
144 : : }
145 : :
146 : : /*
147 : : * Flush out locally pending SLRU stats entries
148 : : *
149 : : * If nowait is true, this function returns false on lock failure. Otherwise
150 : : * this function always returns true.
151 : : *
152 : : * If nowait is true, this function returns true if the lock could not be
153 : : * acquired. Otherwise return false.
154 : : */
155 : : bool
739 156 : 29982 : pgstat_slru_flush(bool nowait)
157 : : {
158 : 29982 : PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
159 : : int i;
160 : :
161 [ + + ]: 29982 : if (!have_slrustats)
162 : 19191 : return false;
163 : :
164 [ + + ]: 10791 : if (!nowait)
165 : 8649 : LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
166 [ - + ]: 2142 : else if (!LWLockConditionalAcquire(&stats_shmem->lock, LW_EXCLUSIVE))
739 andres@anarazel.de 167 :UBC 0 : return true;
168 : :
739 andres@anarazel.de 169 [ + + ]:CBC 97119 : for (i = 0; i < SLRU_NUM_ELEMENTS; i++)
170 : : {
171 : 86328 : PgStat_SLRUStats *sharedent = &stats_shmem->stats[i];
172 : 86328 : PgStat_SLRUStats *pendingent = &pending_SLRUStats[i];
173 : :
174 : : #define SLRU_ACC(fld) sharedent->fld += pendingent->fld
175 : 86328 : SLRU_ACC(blocks_zeroed);
176 : 86328 : SLRU_ACC(blocks_hit);
177 : 86328 : SLRU_ACC(blocks_read);
178 : 86328 : SLRU_ACC(blocks_written);
179 : 86328 : SLRU_ACC(blocks_exists);
180 : 86328 : SLRU_ACC(flush);
181 : 86328 : SLRU_ACC(truncate);
182 : : #undef SLRU_ACC
183 : : }
184 : :
185 : : /* done, clear the pending entry */
186 [ + - + - : 701415 : MemSet(pending_SLRUStats, 0, sizeof(pending_SLRUStats));
+ - + - +
+ ]
187 : :
188 : 10791 : LWLockRelease(&stats_shmem->lock);
189 : :
190 : 10791 : have_slrustats = false;
191 : :
192 : 10791 : return false;
193 : : }
194 : :
195 : : void
196 : 249 : pgstat_slru_reset_all_cb(TimestampTz ts)
197 : : {
198 [ + + ]: 2241 : for (int i = 0; i < SLRU_NUM_ELEMENTS; i++)
199 : 1992 : pgstat_reset_slru_counter_internal(i, ts);
200 : 249 : }
201 : :
202 : : void
203 : 585 : pgstat_slru_snapshot_cb(void)
204 : : {
205 : 585 : PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
206 : :
207 : 585 : LWLockAcquire(&stats_shmem->lock, LW_SHARED);
208 : :
209 : 585 : memcpy(pgStatLocal.snapshot.slru, &stats_shmem->stats,
210 : : sizeof(stats_shmem->stats));
211 : :
212 : 585 : LWLockRelease(&stats_shmem->lock);
755 213 : 585 : }
214 : :
215 : : /*
216 : : * Returns pointer to entry with counters for given SLRU (based on the name
217 : : * stored in SlruCtl as lwlock tranche name).
218 : : */
219 : : static inline PgStat_SLRUStats *
739 220 : 15478745 : get_slru_entry(int slru_idx)
221 : : {
755 222 : 15478745 : pgstat_assert_is_up();
223 : :
224 : : /*
225 : : * The postmaster should never register any SLRU statistics counts; if it
226 : : * did, the counts would be duplicated into child processes via fork().
227 : : */
228 [ + + - + ]: 15478745 : Assert(IsUnderPostmaster || !IsPostmasterEnvironment);
229 : :
230 [ + - - + ]: 15478745 : Assert((slru_idx >= 0) && (slru_idx < SLRU_NUM_ELEMENTS));
231 : :
739 232 : 15478745 : have_slrustats = true;
233 : :
234 : 15478745 : return &pending_SLRUStats[slru_idx];
235 : : }
236 : :
237 : : static void
238 : 1995 : pgstat_reset_slru_counter_internal(int index, TimestampTz ts)
239 : : {
240 : 1995 : PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
241 : :
242 : 1995 : LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
243 : :
244 : 1995 : memset(&stats_shmem->stats[index], 0, sizeof(PgStat_SLRUStats));
245 : 1995 : stats_shmem->stats[index].stat_reset_timestamp = ts;
246 : :
247 : 1995 : LWLockRelease(&stats_shmem->lock);
755 248 : 1995 : }
|