Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4feba03

Browse files
committed
Rework handling of pending data for backend statistics
9aea73f has added support for backend statistics, relying onPgStat_EntryRef->pending for its data pending for flush. This designlacks in flexibility, because the pending list does some memoryallocation, making it unsuitable if incrementing counters in criticalsections.Pending data of backend statistics is reworked so the implementationdoes not depend on PgStat_EntryRef->pending anymore, relying on a staticarea of memory to store the counters that are flushed when stats arereported to the pgstats dshash. An advantage of this approach is toallow the pending data to be manipulated in critical sections; somepatches are under discussion and require that.The pending data is tracked by PendingBackendStats, local topgstat_backend.c. Two routines are introduced to allow IO statistics toupdate the backend-side counters. have_static_pending_cb andflush_static_cb are used for the flush, instead of flush_pending_cb.Author: Bertrand Drouvot, Michael PaquierDiscussion:https://postgr.es/m/66efowskppsns35v5u2m7k4sdnl7yoz5bo64tdjwq7r5lhplrz@y7dme5xwh2r5
1 parent28de66c commit4feba03

File tree

6 files changed

+116
-73
lines changed

6 files changed

+116
-73
lines changed

‎src/backend/utils/activity/pgstat.c‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,9 +370,9 @@ static const PgStat_KindInfo pgstat_kind_builtin_infos[PGSTAT_KIND_BUILTIN_SIZE]
370370
.shared_size=sizeof(PgStatShared_Backend),
371371
.shared_data_off= offsetof(PgStatShared_Backend,stats),
372372
.shared_data_len=sizeof(((PgStatShared_Backend*)0)->stats),
373-
.pending_size=sizeof(PgStat_BackendPending),
374373

375-
.flush_pending_cb=pgstat_backend_flush_cb,
374+
.have_static_pending_cb=pgstat_backend_have_pending_cb,
375+
.flush_static_cb=pgstat_backend_flush_cb,
376376
.reset_timestamp_cb=pgstat_backend_reset_timestamp_cb,
377377
},
378378

‎src/backend/utils/activity/pgstat_backend.c‎

Lines changed: 92 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
* This statistics kind uses a proc number as object ID for the hash table
1212
* of pgstats. Entries are created each time a process is spawned, and are
1313
* dropped when the process exits. These are not written to the pgstats file
14-
* on disk.
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.
1517
*
1618
* Copyright (c) 2001-2025, PostgreSQL Global Development Group
1719
*
@@ -22,8 +24,49 @@
2224

2325
#include"postgres.h"
2426

27+
#include"storage/bufmgr.h"
28+
#include"utils/memutils.h"
2529
#include"utils/pgstat_internal.h"
2630

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+
*/
36+
staticPgStat_BackendPendingPendingBackendStats;
37+
38+
/*
39+
* Utility routines to report I/O stats for backends, kept here to avoid
40+
* exposing PendingBackendStats to the outside world.
41+
*/
42+
void
43+
pgstat_count_backend_io_op_time(IOObjectio_object,IOContextio_context,
44+
IOOpio_op,instr_timeio_time)
45+
{
46+
Assert(track_io_timing);
47+
48+
if (!pgstat_tracks_backend_bktype(MyBackendType))
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+
57+
void
58+
pgstat_count_backend_io_op(IOObjectio_object,IOContextio_context,
59+
IOOpio_op,uint32cnt,uint64bytes)
60+
{
61+
if (!pgstat_tracks_backend_bktype(MyBackendType))
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+
2770
/*
2871
* Returns statistics of a backend by proc number.
2972
*/
@@ -46,14 +89,21 @@ static void
4689
pgstat_flush_backend_entry_io(PgStat_EntryRef*entry_ref)
4790
{
4891
PgStatShared_Backend*shbackendent;
49-
PgStat_BackendPending*pendingent;
5092
PgStat_BktypeIO*bktype_shstats;
51-
PgStat_PendingIO*pending_io;
93+
PgStat_PendingIOpending_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+
*/
100+
if (pg_memory_is_all_zeros(&PendingBackendStats.pending_io,
101+
sizeof(structPgStat_PendingIO)))
102+
return;
52103

53104
shbackendent= (PgStatShared_Backend*)entry_ref->shared_stats;
54-
pendingent= (PgStat_BackendPending*)entry_ref->pending;
55105
bktype_shstats=&shbackendent->stats.io_stats;
56-
pending_io=&pendingent->pending_io;
106+
pending_io=PendingBackendStats.pending_io;
57107

58108
for (intio_object=0;io_object<IOOBJECT_NUM_TYPES;io_object++)
59109
{
@@ -64,68 +114,74 @@ pgstat_flush_backend_entry_io(PgStat_EntryRef *entry_ref)
64114
instr_timetime;
65115

66116
bktype_shstats->counts[io_object][io_context][io_op]+=
67-
pending_io->counts[io_object][io_context][io_op];
117+
pending_io.counts[io_object][io_context][io_op];
68118
bktype_shstats->bytes[io_object][io_context][io_op]+=
69-
pending_io->bytes[io_object][io_context][io_op];
70-
71-
time=pending_io->pending_times[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];
72121

73122
bktype_shstats->times[io_object][io_context][io_op]+=
74123
INSTR_TIME_GET_MICROSEC(time);
75124
}
76125
}
77126
}
127+
128+
/*
129+
* Clear out the statistics buffer, so it can be re-used.
130+
*/
131+
MemSet(&PendingBackendStats.pending_io,0,sizeof(PgStat_PendingIO));
78132
}
79133

80134
/*
81-
* Wrapper routine to flush backend statistics.
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.
82139
*/
83-
staticbool
84-
pgstat_flush_backend_entry(PgStat_EntryRef*entry_ref,boolnowait,
85-
bits32flags)
140+
bool
141+
pgstat_flush_backend(boolnowait,bits32flags)
86142
{
143+
PgStat_EntryRef*entry_ref;
144+
87145
if (!pgstat_tracks_backend_bktype(MyBackendType))
88146
return false;
89147

90-
if (!pgstat_lock_entry(entry_ref,nowait))
148+
if (pg_memory_is_all_zeros(&PendingBackendStats,
149+
sizeof(structPgStat_BackendPending)))
91150
return false;
92151

152+
entry_ref=pgstat_get_entry_ref_locked(PGSTAT_KIND_BACKEND,InvalidOid,
153+
MyProcNumber,nowait);
154+
if (!entry_ref)
155+
return true;
156+
93157
/* Flush requested statistics */
94158
if (flags&PGSTAT_BACKEND_FLUSH_IO)
95159
pgstat_flush_backend_entry_io(entry_ref);
96160

97161
pgstat_unlock_entry(entry_ref);
98162

99-
returntrue;
163+
returnfalse;
100164
}
101165

102166
/*
103-
* Callback to flush out locally pending backend statistics.
104-
*
105-
* If no stats have been recorded, this function returns false.
167+
* Check if there are any backend stats waiting for flush.
106168
*/
107169
bool
108-
pgstat_backend_flush_cb(PgStat_EntryRef*entry_ref,boolnowait)
170+
pgstat_backend_have_pending_cb(void)
109171
{
110-
returnpgstat_flush_backend_entry(entry_ref,nowait,PGSTAT_BACKEND_FLUSH_ALL);
172+
return (!pg_memory_is_all_zeros(&PendingBackendStats,
173+
sizeof(structPgStat_BackendPending)));
111174
}
112175

113176
/*
114-
*Flushout locally pending backend statistics
177+
*Callback to flushout locally pending backend statistics.
115178
*
116-
*"flags" parameter controls which statisticstoflush.
179+
*If some stats could not be flushed duetolock contention, return true.
117180
*/
118-
void
119-
pgstat_flush_backend(boolnowait,bits32flags)
181+
bool
182+
pgstat_backend_flush_cb(boolnowait)
120183
{
121-
PgStat_EntryRef*entry_ref;
122-
123-
if (!pgstat_tracks_backend_bktype(MyBackendType))
124-
return;
125-
126-
entry_ref=pgstat_get_entry_ref(PGSTAT_KIND_BACKEND,InvalidOid,
127-
MyProcNumber, false,NULL);
128-
(void)pgstat_flush_backend_entry(entry_ref,nowait,flags);
184+
returnpgstat_flush_backend(nowait,PGSTAT_BACKEND_FLUSH_ALL);
129185
}
130186

131187
/*
@@ -137,30 +193,18 @@ pgstat_create_backend(ProcNumber procnum)
137193
PgStat_EntryRef*entry_ref;
138194
PgStatShared_Backend*shstatent;
139195

140-
entry_ref=pgstat_prep_pending_entry(PGSTAT_KIND_BACKEND,InvalidOid,
141-
procnum,NULL);
142-
196+
entry_ref=pgstat_get_entry_ref_locked(PGSTAT_KIND_BACKEND,InvalidOid,
197+
MyProcNumber, false);
143198
shstatent= (PgStatShared_Backend*)entry_ref->shared_stats;
144199

145200
/*
146201
* NB: need to accept that there might be stats from an older backend,
147202
* e.g. if we previously used this proc number.
148203
*/
149204
memset(&shstatent->stats,0,sizeof(shstatent->stats));
150-
}
151-
152-
/*
153-
* Find or create a local PgStat_BackendPending entry for proc number.
154-
*/
155-
PgStat_BackendPending*
156-
pgstat_prep_backend_pending(ProcNumberprocnum)
157-
{
158-
PgStat_EntryRef*entry_ref;
159-
160-
entry_ref=pgstat_prep_pending_entry(PGSTAT_KIND_BACKEND,InvalidOid,
161-
procnum,NULL);
205+
pgstat_unlock_entry(entry_ref);
162206

163-
returnentry_ref->pending;
207+
MemSet(&PendingBackendStats,0,sizeof(PgStat_BackendPending));
164208
}
165209

166210
/*

‎src/backend/utils/activity/pgstat_io.c‎

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,12 @@ pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op,
7373
Assert(pgstat_is_ioop_tracked_in_bytes(io_op)||bytes==0);
7474
Assert(pgstat_tracks_io_op(MyBackendType,io_object,io_context,io_op));
7575

76-
if (pgstat_tracks_backend_bktype(MyBackendType))
77-
{
78-
PgStat_BackendPending*entry_ref;
79-
80-
entry_ref=pgstat_prep_backend_pending(MyProcNumber);
81-
entry_ref->pending_io.counts[io_object][io_context][io_op]+=cnt;
82-
entry_ref->pending_io.bytes[io_object][io_context][io_op]+=bytes;
83-
}
84-
8576
PendingIOStats.counts[io_object][io_context][io_op]+=cnt;
8677
PendingIOStats.bytes[io_object][io_context][io_op]+=bytes;
8778

79+
/* Add the per-backend counts */
80+
pgstat_count_backend_io_op(io_object,io_context,io_op,cnt,bytes);
81+
8882
have_iostats= true;
8983
}
9084

@@ -145,14 +139,9 @@ pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op,
145139
INSTR_TIME_ADD(PendingIOStats.pending_times[io_object][io_context][io_op],
146140
io_time);
147141

148-
if (pgstat_tracks_backend_bktype(MyBackendType))
149-
{
150-
PgStat_BackendPending*entry_ref;
151-
152-
entry_ref=pgstat_prep_backend_pending(MyProcNumber);
153-
INSTR_TIME_ADD(entry_ref->pending_io.pending_times[io_object][io_context][io_op],
154-
io_time);
155-
}
142+
/* Add the per-backend count */
143+
pgstat_count_backend_io_op_time(io_object,io_context,io_op,
144+
io_time);
156145
}
157146

158147
pgstat_count_io_op(io_object,io_context,io_op,cnt,bytes);

‎src/backend/utils/activity/pgstat_relation.c‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
264264
* VACUUM command has processed all tables and committed.
265265
*/
266266
pgstat_flush_io(false);
267-
pgstat_flush_backend(false,PGSTAT_BACKEND_FLUSH_IO);
267+
(void)pgstat_flush_backend(false,PGSTAT_BACKEND_FLUSH_IO);
268268
}
269269

270270
/*
@@ -351,7 +351,7 @@ pgstat_report_analyze(Relation rel,
351351

352352
/* see pgstat_report_vacuum() */
353353
pgstat_flush_io(false);
354-
pgstat_flush_backend(false,PGSTAT_BACKEND_FLUSH_IO);
354+
(void)pgstat_flush_backend(false,PGSTAT_BACKEND_FLUSH_IO);
355355
}
356356

357357
/*

‎src/include/pgstat.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,15 @@ extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void);
540540
* Functions in pgstat_backend.c
541541
*/
542542

543+
/* used by pgstat_io.c for I/O stats tracked in backends */
544+
externvoidpgstat_count_backend_io_op_time(IOObjectio_object,
545+
IOContextio_context,
546+
IOOpio_op,
547+
instr_timeio_time);
548+
externvoidpgstat_count_backend_io_op(IOObjectio_object,
549+
IOContextio_context,
550+
IOOpio_op,uint32cnt,
551+
uint64bytes);
543552
externPgStat_Backend*pgstat_fetch_stat_backend(ProcNumberprocNumber);
544553
externboolpgstat_tracks_backend_bktype(BackendTypebktype);
545554
externvoidpgstat_create_backend(ProcNumberprocnum);

‎src/include/utils/pgstat_internal.h‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -624,10 +624,11 @@ extern void pgstat_archiver_snapshot_cb(void);
624624
#definePGSTAT_BACKEND_FLUSH_IO(1 << 0)/* Flush I/O statistics */
625625
#definePGSTAT_BACKEND_FLUSH_ALL(PGSTAT_BACKEND_FLUSH_IO)
626626

627-
externvoidpgstat_flush_backend(boolnowait,bits32flags);
628-
externPgStat_BackendPending*pgstat_prep_backend_pending(ProcNumberprocnum);
629-
externboolpgstat_backend_flush_cb(PgStat_EntryRef*entry_ref,boolnowait);
630-
externvoidpgstat_backend_reset_timestamp_cb(PgStatShared_Common*header,TimestampTzts);
627+
externboolpgstat_flush_backend(boolnowait,bits32flags);
628+
externboolpgstat_backend_flush_cb(boolnowait);
629+
externboolpgstat_backend_have_pending_cb(void);
630+
externvoidpgstat_backend_reset_timestamp_cb(PgStatShared_Common*header,
631+
TimestampTzts);
631632

632633
/*
633634
* Functions in pgstat_bgwriter.c

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp