1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-19 13:42:17 +03:00

Optimize shared memory usage for WaitLSNProcInfo

We need separate pairing heaps for different WaitLSNType's, because there
might be waiters for different LSN's at the same time.  However, one process
can wait only for one type of LSN at a time.  So, no need for inHeap
and heapNode fields to be arrays.

Discussion: https://postgr.es/m/CAPpHfdsBR-7sDtXFJ1qpJtKiohfGoj%3DvqzKVjWxtWsWidx7G_A%40mail.gmail.com
Author: Alexander Korotkov <aekorotkov@gmail.com>
Reviewed-by: Xuneng Zhou <xunengzhou@gmail.com>
This commit is contained in:
Alexander Korotkov
2025-11-18 09:50:12 +02:00
parent 694b4ab33b
commit 75e82b2f5a
2 changed files with 29 additions and 27 deletions

View File

@@ -90,7 +90,7 @@ WaitLSNShmemInit(void)
for (i = 0; i < WAIT_LSN_TYPE_COUNT; i++) for (i = 0; i < WAIT_LSN_TYPE_COUNT; i++)
{ {
pg_atomic_init_u64(&waitLSNState->minWaitedLSN[i], PG_UINT64_MAX); pg_atomic_init_u64(&waitLSNState->minWaitedLSN[i], PG_UINT64_MAX);
pairingheap_initialize(&waitLSNState->waitersHeap[i], waitlsn_cmp, (void *) (uintptr_t) i); pairingheap_initialize(&waitLSNState->waitersHeap[i], waitlsn_cmp, NULL);
} }
/* Initialize process info array */ /* Initialize process info array */
@@ -106,9 +106,8 @@ WaitLSNShmemInit(void)
static int static int
waitlsn_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg) waitlsn_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg)
{ {
int i = (uintptr_t) arg; const WaitLSNProcInfo *aproc = pairingheap_const_container(WaitLSNProcInfo, heapNode, a);
const WaitLSNProcInfo *aproc = pairingheap_const_container(WaitLSNProcInfo, heapNode[i], a); const WaitLSNProcInfo *bproc = pairingheap_const_container(WaitLSNProcInfo, heapNode, b);
const WaitLSNProcInfo *bproc = pairingheap_const_container(WaitLSNProcInfo, heapNode[i], b);
if (aproc->waitLSN < bproc->waitLSN) if (aproc->waitLSN < bproc->waitLSN)
return 1; return 1;
@@ -132,7 +131,7 @@ updateMinWaitedLSN(WaitLSNType lsnType)
if (!pairingheap_is_empty(&waitLSNState->waitersHeap[i])) if (!pairingheap_is_empty(&waitLSNState->waitersHeap[i]))
{ {
pairingheap_node *node = pairingheap_first(&waitLSNState->waitersHeap[i]); pairingheap_node *node = pairingheap_first(&waitLSNState->waitersHeap[i]);
WaitLSNProcInfo *procInfo = pairingheap_container(WaitLSNProcInfo, heapNode[i], node); WaitLSNProcInfo *procInfo = pairingheap_container(WaitLSNProcInfo, heapNode, node);
minWaitedLSN = procInfo->waitLSN; minWaitedLSN = procInfo->waitLSN;
} }
@@ -154,10 +153,11 @@ addLSNWaiter(XLogRecPtr lsn, WaitLSNType lsnType)
procInfo->procno = MyProcNumber; procInfo->procno = MyProcNumber;
procInfo->waitLSN = lsn; procInfo->waitLSN = lsn;
procInfo->lsnType = lsnType;
Assert(!procInfo->inHeap[i]); Assert(!procInfo->inHeap);
pairingheap_add(&waitLSNState->waitersHeap[i], &procInfo->heapNode[i]); pairingheap_add(&waitLSNState->waitersHeap[i], &procInfo->heapNode);
procInfo->inHeap[i] = true; procInfo->inHeap = true;
updateMinWaitedLSN(lsnType); updateMinWaitedLSN(lsnType);
LWLockRelease(WaitLSNLock); LWLockRelease(WaitLSNLock);
@@ -176,10 +176,12 @@ deleteLSNWaiter(WaitLSNType lsnType)
LWLockAcquire(WaitLSNLock, LW_EXCLUSIVE); LWLockAcquire(WaitLSNLock, LW_EXCLUSIVE);
if (procInfo->inHeap[i]) Assert(procInfo->lsnType == lsnType);
if (procInfo->inHeap)
{ {
pairingheap_remove(&waitLSNState->waitersHeap[i], &procInfo->heapNode[i]); pairingheap_remove(&waitLSNState->waitersHeap[i], &procInfo->heapNode);
procInfo->inHeap[i] = false; procInfo->inHeap = false;
updateMinWaitedLSN(lsnType); updateMinWaitedLSN(lsnType);
} }
@@ -228,7 +230,7 @@ wakeupWaiters(WaitLSNType lsnType, XLogRecPtr currentLSN)
WaitLSNProcInfo *procInfo; WaitLSNProcInfo *procInfo;
/* Get procInfo using appropriate heap node */ /* Get procInfo using appropriate heap node */
procInfo = pairingheap_container(WaitLSNProcInfo, heapNode[i], node); procInfo = pairingheap_container(WaitLSNProcInfo, heapNode, node);
if (XLogRecPtrIsValid(currentLSN) && procInfo->waitLSN > currentLSN) if (XLogRecPtrIsValid(currentLSN) && procInfo->waitLSN > currentLSN)
break; break;
@@ -238,7 +240,7 @@ wakeupWaiters(WaitLSNType lsnType, XLogRecPtr currentLSN)
(void) pairingheap_remove_first(&waitLSNState->waitersHeap[i]); (void) pairingheap_remove_first(&waitLSNState->waitersHeap[i]);
/* Update appropriate flag */ /* Update appropriate flag */
procInfo->inHeap[i] = false; procInfo->inHeap = false;
if (numWakeUpProcs == WAKEUP_PROC_STATIC_ARRAY_SIZE) if (numWakeUpProcs == WAKEUP_PROC_STATIC_ARRAY_SIZE)
break; break;
@@ -289,20 +291,14 @@ WaitLSNCleanup(void)
{ {
if (waitLSNState) if (waitLSNState)
{ {
int i;
/* /*
* We do a fast-path check of the heap flags without the lock. These * We do a fast-path check of the inHeap flag without the lock. This
* flags are set to true only by the process itself. So, it's only * flag is set to true only by the process itself. So, it's only
* possible to get a false positive. But that will be eliminated by a * possible to get a false positive. But that will be eliminated by a
* recheck inside deleteLSNWaiter(). * recheck inside deleteLSNWaiter().
*/ */
if (waitLSNState->procInfos[MyProcNumber].inHeap)
for (i = 0; i < (int) WAIT_LSN_TYPE_COUNT; i++) deleteLSNWaiter(waitLSNState->procInfos[MyProcNumber].lsnType);
{
if (waitLSNState->procInfos[MyProcNumber].inHeap[i])
deleteLSNWaiter((WaitLSNType) i);
}
} }
} }

View File

@@ -50,14 +50,20 @@ typedef struct WaitLSNProcInfo
/* LSN, which this process is waiting for */ /* LSN, which this process is waiting for */
XLogRecPtr waitLSN; XLogRecPtr waitLSN;
/* The type of LSN to wait */
WaitLSNType lsnType;
/* Process to wake up once the waitLSN is reached */ /* Process to wake up once the waitLSN is reached */
ProcNumber procno; ProcNumber procno;
/* Heap membership flags for LSN types */ /*
bool inHeap[WAIT_LSN_TYPE_COUNT]; * Heap membership flag. A process can wait for only one LSN type at a
* time, so a single flag suffices (tracked by the lsnType field).
*/
bool inHeap;
/* Heap nodes for LSN types */ /* Pairing heap node for the waiters' heap (one per process) */
pairingheap_node heapNode[WAIT_LSN_TYPE_COUNT]; pairingheap_node heapNode;
} WaitLSNProcInfo; } WaitLSNProcInfo;
/* /*