mirror of
https://github.com/postgres/postgres.git
synced 2025-04-18 13:44:19 +03:00
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
This commit is contained in:
parent
f5930f9a98
commit
46df9487d9
@ -1226,14 +1226,21 @@ PredicateLockShmemInit(void)
|
||||
*/
|
||||
max_table_size *= 10;
|
||||
|
||||
requestSize = add_size(PredXactListDataSize,
|
||||
(mul_size((Size) max_table_size,
|
||||
sizeof(SERIALIZABLEXACT))));
|
||||
|
||||
PredXact = ShmemInitStruct("PredXactList",
|
||||
PredXactListDataSize,
|
||||
requestSize,
|
||||
&found);
|
||||
Assert(found == IsUnderPostmaster);
|
||||
if (!found)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* clean everything, both the header and the element */
|
||||
memset(PredXact, 0, requestSize);
|
||||
|
||||
dlist_init(&PredXact->availableList);
|
||||
dlist_init(&PredXact->activeList);
|
||||
PredXact->SxactGlobalXmin = InvalidTransactionId;
|
||||
@ -1242,11 +1249,9 @@ PredicateLockShmemInit(void)
|
||||
PredXact->LastSxactCommitSeqNo = FirstNormalSerCommitSeqNo - 1;
|
||||
PredXact->CanPartialClearThrough = 0;
|
||||
PredXact->HavePartialClearedThrough = 0;
|
||||
requestSize = mul_size((Size) max_table_size,
|
||||
sizeof(SERIALIZABLEXACT));
|
||||
PredXact->element = ShmemAlloc(requestSize);
|
||||
PredXact->element
|
||||
= (SERIALIZABLEXACT *) ((char *) PredXact + PredXactListDataSize);
|
||||
/* Add all elements to available list, clean. */
|
||||
memset(PredXact->element, 0, requestSize);
|
||||
for (i = 0; i < max_table_size; i++)
|
||||
{
|
||||
LWLockInitialize(&PredXact->element[i].perXactPredicateListLock,
|
||||
@ -1300,20 +1305,25 @@ PredicateLockShmemInit(void)
|
||||
*/
|
||||
max_table_size *= 5;
|
||||
|
||||
requestSize = RWConflictPoolHeaderDataSize +
|
||||
mul_size((Size) max_table_size,
|
||||
RWConflictDataSize);
|
||||
|
||||
RWConflictPool = ShmemInitStruct("RWConflictPool",
|
||||
RWConflictPoolHeaderDataSize,
|
||||
requestSize,
|
||||
&found);
|
||||
Assert(found == IsUnderPostmaster);
|
||||
if (!found)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* clean everything, including the elements */
|
||||
memset(RWConflictPool, 0, requestSize);
|
||||
|
||||
dlist_init(&RWConflictPool->availableList);
|
||||
requestSize = mul_size((Size) max_table_size,
|
||||
RWConflictDataSize);
|
||||
RWConflictPool->element = ShmemAlloc(requestSize);
|
||||
RWConflictPool->element = (RWConflict) ((char *) RWConflictPool +
|
||||
RWConflictPoolHeaderDataSize);
|
||||
/* Add all elements to available list, clean. */
|
||||
memset(RWConflictPool->element, 0, requestSize);
|
||||
for (i = 0; i < max_table_size; i++)
|
||||
{
|
||||
dlist_push_tail(&RWConflictPool->availableList,
|
||||
|
@ -91,10 +91,28 @@ static void CheckDeadLock(void);
|
||||
|
||||
|
||||
/*
|
||||
* Report shared-memory space needed by InitProcGlobal.
|
||||
* Report shared-memory space needed by PGPROC.
|
||||
*/
|
||||
Size
|
||||
ProcGlobalShmemSize(void)
|
||||
static Size
|
||||
PGProcShmemSize(void)
|
||||
{
|
||||
Size size = 0;
|
||||
Size TotalProcs =
|
||||
add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts));
|
||||
|
||||
size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
|
||||
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
|
||||
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
|
||||
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Report shared-memory space needed by Fast-Path locks.
|
||||
*/
|
||||
static Size
|
||||
FastPathLockShmemSize(void)
|
||||
{
|
||||
Size size = 0;
|
||||
Size TotalProcs =
|
||||
@ -102,15 +120,6 @@ ProcGlobalShmemSize(void)
|
||||
Size fpLockBitsSize,
|
||||
fpRelIdSize;
|
||||
|
||||
/* ProcGlobal */
|
||||
size = add_size(size, sizeof(PROC_HDR));
|
||||
size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
|
||||
size = add_size(size, sizeof(slock_t));
|
||||
|
||||
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
|
||||
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
|
||||
size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
|
||||
|
||||
/*
|
||||
* Memory needed for PGPROC fast-path lock arrays. Make sure the sizes are
|
||||
* nicely aligned in each backend.
|
||||
@ -123,6 +132,24 @@ ProcGlobalShmemSize(void)
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Report shared-memory space needed by InitProcGlobal.
|
||||
*/
|
||||
Size
|
||||
ProcGlobalShmemSize(void)
|
||||
{
|
||||
Size size = 0;
|
||||
|
||||
/* ProcGlobal */
|
||||
size = add_size(size, sizeof(PROC_HDR));
|
||||
size = add_size(size, sizeof(slock_t));
|
||||
|
||||
size = add_size(size, PGProcShmemSize());
|
||||
size = add_size(size, FastPathLockShmemSize());
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Report number of semaphores needed by InitProcGlobal.
|
||||
*/
|
||||
@ -175,6 +202,8 @@ InitProcGlobal(void)
|
||||
*fpEndPtr PG_USED_FOR_ASSERTS_ONLY;
|
||||
Size fpLockBitsSize,
|
||||
fpRelIdSize;
|
||||
Size requestSize;
|
||||
char *ptr;
|
||||
|
||||
/* Create the ProcGlobal shared structure */
|
||||
ProcGlobal = (PROC_HDR *)
|
||||
@ -204,8 +233,17 @@ InitProcGlobal(void)
|
||||
* with a single freelist.) Each PGPROC structure is dedicated to exactly
|
||||
* one of these purposes, and they do not move between groups.
|
||||
*/
|
||||
procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC));
|
||||
MemSet(procs, 0, TotalProcs * sizeof(PGPROC));
|
||||
requestSize = PGProcShmemSize();
|
||||
|
||||
ptr = ShmemInitStruct("PGPROC structures",
|
||||
requestSize,
|
||||
&found);
|
||||
|
||||
MemSet(ptr, 0, requestSize);
|
||||
|
||||
procs = (PGPROC *) ptr;
|
||||
ptr = (char *) ptr + TotalProcs * sizeof(PGPROC);
|
||||
|
||||
ProcGlobal->allProcs = procs;
|
||||
/* XXX allProcCount isn't really all of them; it excludes prepared xacts */
|
||||
ProcGlobal->allProcCount = MaxBackends + NUM_AUXILIARY_PROCS;
|
||||
@ -217,13 +255,17 @@ InitProcGlobal(void)
|
||||
* XXX: It might make sense to increase padding for these arrays, given
|
||||
* how hotly they are accessed.
|
||||
*/
|
||||
ProcGlobal->xids =
|
||||
(TransactionId *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->xids));
|
||||
MemSet(ProcGlobal->xids, 0, TotalProcs * sizeof(*ProcGlobal->xids));
|
||||
ProcGlobal->subxidStates = (XidCacheStatus *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->subxidStates));
|
||||
MemSet(ProcGlobal->subxidStates, 0, TotalProcs * sizeof(*ProcGlobal->subxidStates));
|
||||
ProcGlobal->statusFlags = (uint8 *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->statusFlags));
|
||||
MemSet(ProcGlobal->statusFlags, 0, TotalProcs * sizeof(*ProcGlobal->statusFlags));
|
||||
ProcGlobal->xids = (TransactionId *) ptr;
|
||||
ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->xids));
|
||||
|
||||
ProcGlobal->subxidStates = (XidCacheStatus *) ptr;
|
||||
ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->subxidStates));
|
||||
|
||||
ProcGlobal->statusFlags = (uint8 *) ptr;
|
||||
ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags));
|
||||
|
||||
/* make sure wer didn't overflow */
|
||||
Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize));
|
||||
|
||||
/*
|
||||
* Allocate arrays for fast-path locks. Those are variable-length, so
|
||||
@ -233,11 +275,16 @@ InitProcGlobal(void)
|
||||
fpLockBitsSize = MAXALIGN(FastPathLockGroupsPerBackend * sizeof(uint64));
|
||||
fpRelIdSize = MAXALIGN(FastPathLockSlotsPerBackend() * sizeof(Oid));
|
||||
|
||||
fpPtr = ShmemAlloc(TotalProcs * (fpLockBitsSize + fpRelIdSize));
|
||||
MemSet(fpPtr, 0, TotalProcs * (fpLockBitsSize + fpRelIdSize));
|
||||
requestSize = FastPathLockShmemSize();
|
||||
|
||||
fpPtr = ShmemInitStruct("Fast-Path Lock Array",
|
||||
requestSize,
|
||||
&found);
|
||||
|
||||
MemSet(fpPtr, 0, requestSize);
|
||||
|
||||
/* For asserts checking we did not overflow. */
|
||||
fpEndPtr = fpPtr + (TotalProcs * (fpLockBitsSize + fpRelIdSize));
|
||||
fpEndPtr = fpPtr + requestSize;
|
||||
|
||||
for (i = 0; i < TotalProcs; i++)
|
||||
{
|
||||
@ -330,7 +377,9 @@ InitProcGlobal(void)
|
||||
PreparedXactProcs = &procs[MaxBackends + NUM_AUXILIARY_PROCS];
|
||||
|
||||
/* Create ProcStructLock spinlock, too */
|
||||
ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
|
||||
ProcStructLock = (slock_t *) ShmemInitStruct("ProcStructLock spinlock",
|
||||
sizeof(slock_t),
|
||||
&found);
|
||||
SpinLockInit(ProcStructLock);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user