Skip to content

Commit 46df948

Browse files
committed
Improve accounting for PredXactList, RWConflictPool and PGPROC
Various places allocated shared memory by first allocating a small chunk using ShmemInitStruct(), followed by ShmemAlloc() calls to allocate more memory. Unfortunately, ShmemAlloc() does not update ShmemIndex, so this affected pg_shmem_allocations - it only shown the initial chunk. This commit modifies the following allocations, to allocate everything as a single chunk, and then split it internally. - PredXactList - RWConflictPool - PGPROC structures - Fast-Path Lock Array The fast-path lock array is allocated separately, not as a part of the PGPROC structures allocation. Author: Rahila Syed <rahilasyed90@gmail.com> Reviewed-by: Andres Freund <andres@anarazel.de> Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com> Reviewed-by: Tomas Vondra <tomas@vondra.me> Discussion: https://postgr.es/m/CAH2L28vHzRankszhqz7deXURxKncxfirnuW68zD7+hVAqaS5GQ@mail.gmail.com
1 parent f5930f9 commit 46df948

File tree

2 files changed

+91
-32
lines changed

2 files changed

+91
-32
lines changed

src/backend/storage/lmgr/predicate.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,14 +1226,21 @@ PredicateLockShmemInit(void)
12261226
*/
12271227
max_table_size *= 10;
12281228

1229+
requestSize = add_size(PredXactListDataSize,
1230+
(mul_size((Size) max_table_size,
1231+
sizeof(SERIALIZABLEXACT))));
1232+
12291233
PredXact = ShmemInitStruct("PredXactList",
1230-
PredXactListDataSize,
1234+
requestSize,
12311235
&found);
12321236
Assert(found == IsUnderPostmaster);
12331237
if (!found)
12341238
{
12351239
int i;
12361240

1241+
/* clean everything, both the header and the element */
1242+
memset(PredXact, 0, requestSize);
1243+
12371244
dlist_init(&PredXact->availableList);
12381245
dlist_init(&PredXact->activeList);
12391246
PredXact->SxactGlobalXmin = InvalidTransactionId;
@@ -1242,11 +1249,9 @@ PredicateLockShmemInit(void)
12421249
PredXact->LastSxactCommitSeqNo = FirstNormalSerCommitSeqNo - 1;
12431250
PredXact->CanPartialClearThrough = 0;
12441251
PredXact->HavePartialClearedThrough = 0;
1245-
requestSize = mul_size((Size) max_table_size,
1246-
sizeof(SERIALIZABLEXACT));
1247-
PredXact->element = ShmemAlloc(requestSize);
1252+
PredXact->element
1253+
= (SERIALIZABLEXACT *) ((char *) PredXact + PredXactListDataSize);
12481254
/* Add all elements to available list, clean. */
1249-
memset(PredXact->element, 0, requestSize);
12501255
for (i = 0; i < max_table_size; i++)
12511256
{
12521257
LWLockInitialize(&PredXact->element[i].perXactPredicateListLock,
@@ -1300,20 +1305,25 @@ PredicateLockShmemInit(void)
13001305
*/
13011306
max_table_size *= 5;
13021307

1308+
requestSize = RWConflictPoolHeaderDataSize +
1309+
mul_size((Size) max_table_size,
1310+
RWConflictDataSize);
1311+
13031312
RWConflictPool = ShmemInitStruct("RWConflictPool",
1304-
RWConflictPoolHeaderDataSize,
1313+
requestSize,
13051314
&found);
13061315
Assert(found == IsUnderPostmaster);
13071316
if (!found)
13081317
{
13091318
int i;
13101319

1320+
/* clean everything, including the elements */
1321+
memset(RWConflictPool, 0, requestSize);
1322+
13111323
dlist_init(&RWConflictPool->availableList);
1312-
requestSize = mul_size((Size) max_table_size,
1313-
RWConflictDataSize);
1314-
RWConflictPool->element = ShmemAlloc(requestSize);
1324+
RWConflictPool->element = (RWConflict) ((char *) RWConflictPool +
1325+
RWConflictPoolHeaderDataSize);
13151326
/* Add all elements to available list, clean. */
1316-
memset(RWConflictPool->element, 0, requestSize);
13171327
for (i = 0; i < max_table_size; i++)
13181328
{
13191329
dlist_push_tail(&RWConflictPool->availableList,

src/backend/storage/lmgr/proc.c

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -91,26 +91,35 @@ static void CheckDeadLock(void);
9191

9292

9393
/*
94-
* Report shared-memory space needed by InitProcGlobal.
94+
* Report shared-memory space needed by PGPROC.
9595
*/
96-
Size
97-
ProcGlobalShmemSize(void)
96+
static Size
97+
PGProcShmemSize(void)
9898
{
9999
Size size = 0;
100100
Size TotalProcs =
101101
add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts));
102-
Size fpLockBitsSize,
103-
fpRelIdSize;
104102

105-
/* ProcGlobal */
106-
size = add_size(size, sizeof(PROC_HDR));
107103
size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
108-
size = add_size(size, sizeof(slock_t));
109-
110104
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
111105
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
112106
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
113107

108+
return size;
109+
}
110+
111+
/*
112+
* Report shared-memory space needed by Fast-Path locks.
113+
*/
114+
static Size
115+
FastPathLockShmemSize(void)
116+
{
117+
Size size = 0;
118+
Size TotalProcs =
119+
add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts));
120+
Size fpLockBitsSize,
121+
fpRelIdSize;
122+
114123
/*
115124
* Memory needed for PGPROC fast-path lock arrays. Make sure the sizes are
116125
* nicely aligned in each backend.
@@ -123,6 +132,24 @@ ProcGlobalShmemSize(void)
123132
return size;
124133
}
125134

135+
/*
136+
* Report shared-memory space needed by InitProcGlobal.
137+
*/
138+
Size
139+
ProcGlobalShmemSize(void)
140+
{
141+
Size size = 0;
142+
143+
/* ProcGlobal */
144+
size = add_size(size, sizeof(PROC_HDR));
145+
size = add_size(size, sizeof(slock_t));
146+
147+
size = add_size(size, PGProcShmemSize());
148+
size = add_size(size, FastPathLockShmemSize());
149+
150+
return size;
151+
}
152+
126153
/*
127154
* Report number of semaphores needed by InitProcGlobal.
128155
*/
@@ -175,6 +202,8 @@ InitProcGlobal(void)
175202
*fpEndPtr PG_USED_FOR_ASSERTS_ONLY;
176203
Size fpLockBitsSize,
177204
fpRelIdSize;
205+
Size requestSize;
206+
char *ptr;
178207

179208
/* Create the ProcGlobal shared structure */
180209
ProcGlobal = (PROC_HDR *)
@@ -204,8 +233,17 @@ InitProcGlobal(void)
204233
* with a single freelist.) Each PGPROC structure is dedicated to exactly
205234
* one of these purposes, and they do not move between groups.
206235
*/
207-
procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC));
208-
MemSet(procs, 0, TotalProcs * sizeof(PGPROC));
236+
requestSize = PGProcShmemSize();
237+
238+
ptr = ShmemInitStruct("PGPROC structures",
239+
requestSize,
240+
&found);
241+
242+
MemSet(ptr, 0, requestSize);
243+
244+
procs = (PGPROC *) ptr;
245+
ptr = (char *) ptr + TotalProcs * sizeof(PGPROC);
246+
209247
ProcGlobal->allProcs = procs;
210248
/* XXX allProcCount isn't really all of them; it excludes prepared xacts */
211249
ProcGlobal->allProcCount = MaxBackends + NUM_AUXILIARY_PROCS;
@@ -217,13 +255,17 @@ InitProcGlobal(void)
217255
* XXX: It might make sense to increase padding for these arrays, given
218256
* how hotly they are accessed.
219257
*/
220-
ProcGlobal->xids =
221-
(TransactionId *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->xids));
222-
MemSet(ProcGlobal->xids, 0, TotalProcs * sizeof(*ProcGlobal->xids));
223-
ProcGlobal->subxidStates = (XidCacheStatus *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->subxidStates));
224-
MemSet(ProcGlobal->subxidStates, 0, TotalProcs * sizeof(*ProcGlobal->subxidStates));
225-
ProcGlobal->statusFlags = (uint8 *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->statusFlags));
226-
MemSet(ProcGlobal->statusFlags, 0, TotalProcs * sizeof(*ProcGlobal->statusFlags));
258+
ProcGlobal->xids = (TransactionId *) ptr;
259+
ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->xids));
260+
261+
ProcGlobal->subxidStates = (XidCacheStatus *) ptr;
262+
ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->subxidStates));
263+
264+
ProcGlobal->statusFlags = (uint8 *) ptr;
265+
ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags));
266+
267+
/* make sure wer didn't overflow */
268+
Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize));
227269

228270
/*
229271
* Allocate arrays for fast-path locks. Those are variable-length, so
@@ -233,11 +275,16 @@ InitProcGlobal(void)
233275
fpLockBitsSize = MAXALIGN(FastPathLockGroupsPerBackend * sizeof(uint64));
234276
fpRelIdSize = MAXALIGN(FastPathLockSlotsPerBackend() * sizeof(Oid));
235277

236-
fpPtr = ShmemAlloc(TotalProcs * (fpLockBitsSize + fpRelIdSize));
237-
MemSet(fpPtr, 0, TotalProcs * (fpLockBitsSize + fpRelIdSize));
278+
requestSize = FastPathLockShmemSize();
279+
280+
fpPtr = ShmemInitStruct("Fast-Path Lock Array",
281+
requestSize,
282+
&found);
283+
284+
MemSet(fpPtr, 0, requestSize);
238285

239286
/* For asserts checking we did not overflow. */
240-
fpEndPtr = fpPtr + (TotalProcs * (fpLockBitsSize + fpRelIdSize));
287+
fpEndPtr = fpPtr + requestSize;
241288

242289
for (i = 0; i < TotalProcs; i++)
243290
{
@@ -330,7 +377,9 @@ InitProcGlobal(void)
330377
PreparedXactProcs = &procs[MaxBackends + NUM_AUXILIARY_PROCS];
331378

332379
/* Create ProcStructLock spinlock, too */
333-
ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
380+
ProcStructLock = (slock_t *) ShmemInitStruct("ProcStructLock spinlock",
381+
sizeof(slock_t),
382+
&found);
334383
SpinLockInit(ProcStructLock);
335384
}
336385

0 commit comments

Comments
 (0)