Skip to content

Commit 452ab23

Browse files
committed
Refactor LWLocks and pg_stat_activity new field
1 parent 0e42397 commit 452ab23

File tree

29 files changed

+631
-218
lines changed

29 files changed

+631
-218
lines changed

doc/src/sgml/monitoring.sgml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,11 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
629629
<entry><type>boolean</></entry>
630630
<entry>True if this backend is currently waiting on a lock</entry>
631631
</row>
632+
<row>
633+
<entry><structfield>wait_event</></entry>
634+
<entry><type>text</></entry>
635+
<entry>Name of a current wait event in backend</entry>
636+
</row>
632637
<row>
633638
<entry><structfield>state</></entry>
634639
<entry><type>text</></entry>

src/backend/access/transam/clog.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,8 @@ CLOGShmemInit(void)
457457
{
458458
ClogCtl->PagePrecedes = CLOGPagePrecedes;
459459
SimpleLruInit(ClogCtl, "CLOG Ctl", CLOGShmemBuffers(), CLOG_LSNS_PER_PAGE,
460-
CLogControlLock, "pg_clog");
460+
CLogControlLock, "pg_clog",
461+
"CLogBufferLocks");
461462
}
462463

463464
/*

src/backend/access/transam/commit_ts.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,8 @@ CommitTsShmemInit(void)
466466

467467
CommitTsCtl->PagePrecedes = CommitTsPagePrecedes;
468468
SimpleLruInit(CommitTsCtl, "CommitTs Ctl", CommitTsShmemBuffers(), 0,
469-
CommitTsControlLock, "pg_commit_ts");
469+
CommitTsControlLock, "pg_commit_ts",
470+
"CommitTSBufferLocks");
470471

471472
commitTsShared = ShmemInitStruct("CommitTs shared",
472473
sizeof(CommitTimestampShared),

src/backend/access/transam/multixact.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,10 +1842,12 @@ MultiXactShmemInit(void)
18421842

18431843
SimpleLruInit(MultiXactOffsetCtl,
18441844
"MultiXactOffset Ctl", NUM_MXACTOFFSET_BUFFERS, 0,
1845-
MultiXactOffsetControlLock, "pg_multixact/offsets");
1845+
MultiXactOffsetControlLock, "pg_multixact/offsets",
1846+
"MultiXactOffsetBufferLocks");
18461847
SimpleLruInit(MultiXactMemberCtl,
18471848
"MultiXactMember Ctl", NUM_MXACTMEMBER_BUFFERS, 0,
1848-
MultiXactMemberControlLock, "pg_multixact/members");
1849+
MultiXactMemberControlLock, "pg_multixact/members",
1850+
"MultiXactMemberBufferLocks");
18491851

18501852
/* Initialize our shared state struct */
18511853
MultiXactState = ShmemInitStruct("Shared MultiXact State",

src/backend/access/transam/slru.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,20 @@ SimpleLruShmemSize(int nslots, int nlsns)
156156
if (nlsns > 0)
157157
sz += MAXALIGN(nslots * nlsns * sizeof(XLogRecPtr)); /* group_lsn[] */
158158

159+
/* size of lwlocks */
160+
sz = add_size(sz, LWLockTrancheShmemSize(nslots));
161+
159162
return BUFFERALIGN(sz) + BLCKSZ * nslots;
160163
}
161164

162165
void
163166
SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
164-
LWLock *ctllock, const char *subdir)
167+
LWLock *ctllock, const char *subdir,
168+
const char *lwlocks_tranche)
165169
{
166-
SlruShared shared;
167-
bool found;
170+
SlruShared shared;
171+
bool found;
172+
LWLockPadded *lwlock_array;
168173

169174
shared = (SlruShared) ShmemInitStruct(name,
170175
SimpleLruShmemSize(nslots, nlsns),
@@ -212,13 +217,18 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
212217
}
213218

214219
ptr += BUFFERALIGN(offset);
220+
221+
/* Create tranche and lwlocks required for slots */
222+
LWLockCreateTranche(lwlocks_tranche, nslots, &lwlock_array);
223+
224+
/* Initialize slots */
215225
for (slotno = 0; slotno < nslots; slotno++)
216226
{
217227
shared->page_buffer[slotno] = ptr;
218228
shared->page_status[slotno] = SLRU_PAGE_EMPTY;
219229
shared->page_dirty[slotno] = false;
220230
shared->page_lru_count[slotno] = 0;
221-
shared->buffer_locks[slotno] = LWLockAssign();
231+
shared->buffer_locks[slotno] = &lwlock_array[slotno].lock;
222232
ptr += BLCKSZ;
223233
}
224234
}

src/backend/access/transam/subtrans.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ SUBTRANSShmemInit(void)
179179
{
180180
SubTransCtl->PagePrecedes = SubTransPagePrecedes;
181181
SimpleLruInit(SubTransCtl, "SUBTRANS Ctl", NUM_SUBTRANS_BUFFERS, 0,
182-
SubtransControlLock, "pg_subtrans");
182+
SubtransControlLock, "pg_subtrans",
183+
"SubtransBufferLocks");
183184
/* Override default assumption that writes should be fsync'd */
184185
SubTransCtl->do_fsync = false;
185186
}

src/backend/access/transam/xlog.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4679,11 +4679,12 @@ XLOGShmemInit(void)
46794679

46804680
XLogCtl->Insert.WALInsertLockTrancheId = LWLockNewTrancheId();
46814681

4682-
XLogCtl->Insert.WALInsertLockTranche.name = "WALInsertLocks";
4682+
strcpy(XLogCtl->Insert.WALInsertLockTranche.name, "WALInsertLocks");
46834683
XLogCtl->Insert.WALInsertLockTranche.array_base = WALInsertLocks;
46844684
XLogCtl->Insert.WALInsertLockTranche.array_stride = sizeof(WALInsertLockPadded);
46854685

4686-
LWLockRegisterTranche(XLogCtl->Insert.WALInsertLockTrancheId, &XLogCtl->Insert.WALInsertLockTranche);
4686+
LWLockRegisterTranche(XLogCtl->Insert.WALInsertLockTrancheId,
4687+
&XLogCtl->Insert.WALInsertLockTranche);
46874688
for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
46884689
{
46894690
LWLockInitialize(&WALInsertLocks[i].l.lock,

src/backend/catalog/system_views.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ CREATE VIEW pg_stat_activity AS
623623
S.query_start,
624624
S.state_change,
625625
S.waiting,
626+
S.wait_event,
626627
S.state,
627628
S.backend_xid,
628629
s.backend_xmin,

src/backend/commands/async.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ AsyncShmemInit(void)
469469
*/
470470
AsyncCtl->PagePrecedes = asyncQueuePagePrecedes;
471471
SimpleLruInit(AsyncCtl, "Async Ctl", NUM_ASYNC_BUFFERS, 0,
472-
AsyncCtlLock, "pg_notify");
472+
AsyncCtlLock, "pg_notify", "AsyncBufferLocks");
473473
/* Override default assumption that writes should be fsync'd */
474474
AsyncCtl->do_fsync = false;
475475

src/backend/libpq/be-secure.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "tcop/tcopprot.h"
3737
#include "utils/memutils.h"
3838
#include "storage/proc.h"
39+
#include "pgstat.h"
3940

4041

4142
char *ssl_cert_file;
@@ -122,6 +123,8 @@ secure_read(Port *port, void *ptr, size_t len)
122123
ssize_t n;
123124
int waitfor;
124125

126+
pgstat_report_wait_start(WAIT_NETWORK, WAIT_NETWORK_READ);
127+
125128
retry:
126129
#ifdef USE_SSL
127130
waitfor = 0;
@@ -168,6 +171,7 @@ secure_read(Port *port, void *ptr, size_t len)
168171
* interrupts from being processed.
169172
*/
170173
ProcessClientReadInterrupt(false);
174+
pgstat_report_wait_end();
171175

172176
return n;
173177
}
@@ -202,6 +206,8 @@ secure_write(Port *port, void *ptr, size_t len)
202206
ssize_t n;
203207
int waitfor;
204208

209+
pgstat_report_wait_start(WAIT_NETWORK, WAIT_NETWORK_WRITE);
210+
205211
retry:
206212
waitfor = 0;
207213
#ifdef USE_SSL
@@ -247,6 +253,7 @@ secure_write(Port *port, void *ptr, size_t len)
247253
* interrupts from being processed.
248254
*/
249255
ProcessClientWriteInterrupt(false);
256+
pgstat_report_wait_end();
250257

251258
return n;
252259
}

src/backend/port/unix_latch.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "storage/latch.h"
5656
#include "storage/pmsignal.h"
5757
#include "storage/shmem.h"
58+
#include "pgstat.h"
5859

5960
/* Are we currently in WaitLatch? The signal handler would like to know. */
6061
static volatile sig_atomic_t waiting = false;
@@ -262,6 +263,8 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
262263
#endif
263264
}
264265

266+
pgstat_report_wait_start(WAIT_LATCH, 0);
267+
265268
waiting = true;
266269
do
267270
{
@@ -500,6 +503,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
500503
}
501504
} while (result == 0);
502505
waiting = false;
506+
pgstat_report_wait_end();
503507

504508
return result;
505509
}

src/backend/port/win32_latch.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
177177
/* Ensure that signals are serviced even if latch is already set */
178178
pgwin32_dispatch_queued_signals();
179179

180+
pgstat_report_wait_start(WAIT_LATCH, 0);
181+
180182
do
181183
{
182184
/*
@@ -278,6 +280,8 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
278280
}
279281
} while (result == 0);
280282

283+
pgstat_report_wait_end();
284+
281285
/* Clean up the event object we created for the socket */
282286
if (sockevent != WSA_INVALID_EVENT)
283287
{

src/backend/postmaster/pgstat.c

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "storage/fd.h"
5555
#include "storage/ipc.h"
5656
#include "storage/latch.h"
57+
#include "storage/lwlock.h"
5758
#include "storage/pg_shmem.h"
5859
#include "storage/procsignal.h"
5960
#include "storage/sinvaladt.h"
@@ -99,7 +100,6 @@
99100
#define PGSTAT_TAB_HASH_SIZE 512
100101
#define PGSTAT_FUNCTION_HASH_SIZE 512
101102

102-
103103
/* ----------
104104
* GUC parameters
105105
* ----------
@@ -242,6 +242,16 @@ static volatile bool got_SIGHUP = false;
242242
*/
243243
static instr_time total_func_time;
244244

245+
/* Names of WAIT_CLASSES */
246+
static const char *WAIT_CLASS_NAMES[] =
247+
{
248+
"",
249+
"LWLocks",
250+
"Locks",
251+
"Storage",
252+
"Latch",
253+
"Network"
254+
};
245255

246256
/* ----------
247257
* Local function forward declarations
@@ -2929,6 +2939,89 @@ pgstat_report_waiting(bool waiting)
29292939
beentry->st_waiting = waiting;
29302940
}
29312941

2942+
/*
2943+
* pgstat_get_wait_class_name() -
2944+
*
2945+
* Return wait class name for given class
2946+
*/
2947+
2948+
const char *
2949+
pgstat_get_wait_class_name(uint8 classId)
2950+
{
2951+
return WAIT_CLASS_NAMES[classId];
2952+
}
2953+
2954+
/*
2955+
* pgstat_get_wait_event_name() -
2956+
*
2957+
* Return wait event name for the given class and event
2958+
*/
2959+
const char *
2960+
pgstat_get_wait_event_name(uint8 classId, uint8 eventId)
2961+
{
2962+
static const char *eventsIO[] = {"READ", "WRITE"};
2963+
static const char *empty = "";
2964+
2965+
switch (classId)
2966+
{
2967+
case WAIT_LOCK: return LOCK_NAMES[eventId];
2968+
case WAIT_LWLOCK: return LWLOCK_TRANCHE_NAME(eventId);
2969+
case WAIT_IO: /* fallthrough */;
2970+
case WAIT_NETWORK: return eventsIO[eventId];
2971+
case WAIT_LATCH: return WAIT_CLASS_NAMES[WAIT_LATCH];
2972+
};
2973+
return empty;
2974+
}
2975+
2976+
/* ----------
2977+
* pgstat_report_wait_start() -
2978+
*
2979+
* Called from backends to report wait event type information.
2980+
*
2981+
* NB: this *must* be able to survive being called before MyBEEntry has been
2982+
* initialized.
2983+
* ----------
2984+
*/
2985+
void
2986+
pgstat_report_wait_start(uint8 classId, uint8 eventId)
2987+
{
2988+
volatile PgBackendStatus *beentry = MyBEEntry;
2989+
2990+
if (!pgstat_track_activities || !beentry)
2991+
return;
2992+
2993+
/* prevent nested waits */
2994+
if (beentry->st_wait_nested++ > 0)
2995+
return;
2996+
2997+
/*
2998+
* Since this is a uint32 field in a struct that only this process
2999+
* may modify, there seems no need to bother with the st_changecount
3000+
* protocol. The update must appear atomic in any case.
3001+
*/
3002+
beentry->st_wait_data = ((uint32)classId << 8) + eventId;
3003+
}
3004+
3005+
/* ----------
3006+
* pgstat_report_wait_end() -
3007+
*
3008+
* Called from backends, indicates that wait was ended
3009+
* ---------
3010+
*/
3011+
void
3012+
pgstat_report_wait_end()
3013+
{
3014+
volatile PgBackendStatus *beentry = MyBEEntry;
3015+
3016+
if (!pgstat_track_activities || !beentry)
3017+
return;
3018+
3019+
/* prevent nested waits */
3020+
if ((--beentry->st_wait_nested) > 0)
3021+
return;
3022+
3023+
beentry->st_wait_data = 0;
3024+
}
29323025

29333026
/* ----------
29343027
* pgstat_read_current_status() -

src/backend/replication/logical/origin.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ ReplicationOriginShmemInit(void)
470470
int i;
471471

472472
replication_states_ctl->tranche_id = LWLockNewTrancheId();
473-
replication_states_ctl->tranche.name = "ReplicationOrigins";
473+
strcpy(replication_states_ctl->tranche.name, "ReplicationOrigins");
474474
replication_states_ctl->tranche.array_base =
475475
&replication_states[0].lock;
476476
replication_states_ctl->tranche.array_stride =

src/backend/replication/slot.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ ReplicationSlotsShmemSize(void)
118118
size = add_size(size,
119119
mul_size(max_replication_slots, sizeof(ReplicationSlot)));
120120

121+
/* size of lwlocks */
122+
size = add_size(size, LWLockTrancheShmemSize(max_replication_slots));
123+
121124
return size;
122125
}
123126

@@ -127,7 +130,8 @@ ReplicationSlotsShmemSize(void)
127130
void
128131
ReplicationSlotsShmemInit(void)
129132
{
130-
bool found;
133+
bool found;
134+
LWLockPadded *lwlocks_array;
131135

132136
if (max_replication_slots == 0)
133137
return;
@@ -143,13 +147,17 @@ ReplicationSlotsShmemInit(void)
143147
/* First time through, so initialize */
144148
MemSet(ReplicationSlotCtl, 0, ReplicationSlotsShmemSize());
145149

150+
/* Create lwlocks */
151+
LWLockCreateTranche("ReplicationSlotLocks", max_replication_slots,
152+
&lwlocks_array);
153+
146154
for (i = 0; i < max_replication_slots; i++)
147155
{
148156
ReplicationSlot *slot = &ReplicationSlotCtl->replication_slots[i];
149157

150158
/* everything else is zeroed by the memset above */
151159
SpinLockInit(&slot->mutex);
152-
slot->io_in_progress_lock = LWLockAssign();
160+
slot->io_in_progress_lock = &lwlocks_array[i].lock;
153161
}
154162
}
155163
}

0 commit comments

Comments
 (0)