Use an LWLock instead of a spinlock in waitlsn.c

This should prevent busy-waiting when number of waiting processes is high.

Discussion: https://postgr.es/m/202404030658.hhj3vfxeyhft%40alvherre.pgsql
Author: Alvaro Herrera
This commit is contained in:
Alexander Korotkov 2024-04-07 00:31:43 +03:00
parent 1577081e96
commit 25f42429e2
4 changed files with 10 additions and 12 deletions

View File

@ -58,7 +58,6 @@ WaitLSNShmemInit(void)
&found);
if (!found)
{
SpinLockInit(&waitLSN->waitersHeapMutex);
pg_atomic_init_u64(&waitLSN->minWaitedLSN, PG_UINT64_MAX);
pairingheap_initialize(&waitLSN->waitersHeap, lsn_cmp, NULL);
memset(&waitLSN->procInfos, 0, MaxBackends * sizeof(WaitLSNProcInfo));
@ -115,13 +114,13 @@ addLSNWaiter(XLogRecPtr lsn)
procInfo->procnum = MyProcNumber;
procInfo->waitLSN = lsn;
SpinLockAcquire(&waitLSN->waitersHeapMutex);
LWLockAcquire(WaitLSNLock, LW_EXCLUSIVE);
pairingheap_add(&waitLSN->waitersHeap, &procInfo->phNode);
procInfo->inHeap = true;
updateMinWaitedLSN();
SpinLockRelease(&waitLSN->waitersHeapMutex);
LWLockRelease(WaitLSNLock);
}
/*
@ -132,11 +131,11 @@ deleteLSNWaiter(void)
{
WaitLSNProcInfo *procInfo = &waitLSN->procInfos[MyProcNumber];
SpinLockAcquire(&waitLSN->waitersHeapMutex);
LWLockAcquire(WaitLSNLock, LW_EXCLUSIVE);
if (!procInfo->inHeap)
{
SpinLockRelease(&waitLSN->waitersHeapMutex);
LWLockRelease(WaitLSNLock);
return;
}
@ -144,7 +143,7 @@ deleteLSNWaiter(void)
procInfo->inHeap = false;
updateMinWaitedLSN();
SpinLockRelease(&waitLSN->waitersHeapMutex);
LWLockRelease(WaitLSNLock);
}
/*
@ -160,7 +159,7 @@ WaitLSNSetLatches(XLogRecPtr currentLSN)
wakeUpProcNums = palloc(sizeof(int) * MaxBackends);
SpinLockAcquire(&waitLSN->waitersHeapMutex);
LWLockAcquire(WaitLSNLock, LW_EXCLUSIVE);
/*
* Iterate the pairing heap of waiting processes till we find LSN not yet
@ -182,7 +181,7 @@ WaitLSNSetLatches(XLogRecPtr currentLSN)
updateMinWaitedLSN();
SpinLockRelease(&waitLSN->waitersHeapMutex);
LWLockRelease(WaitLSNLock);
/*
* Set latches for processes, whose waited LSNs are already replayed. This

View File

@ -345,6 +345,7 @@ WALSummarizer "Waiting to read or update WAL summarization state."
DSMRegistry "Waiting to read or update the dynamic shared memory registry."
InjectionPoint "Waiting to read or update information related to injection points."
SerialControl "Waiting to read or update shared <filename>pg_serial</filename> state."
WaitLSN "Waiting to read or update shared Wait-for-LSN state."
#
# END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE)

View File

@ -55,13 +55,10 @@ typedef struct WaitLSNState
/*
* A pairing heap of waiting processes order by LSN values (least LSN is
* on top).
* on top). Protected by WaitLSNLock.
*/
pairingheap waitersHeap;
/* A mutex protecting the pairing heap above */
slock_t waitersHeapMutex;
/* An array with per-process information, indexed by the process number */
WaitLSNProcInfo procInfos[FLEXIBLE_ARRAY_MEMBER];
} WaitLSNState;

View File

@ -83,3 +83,4 @@ PG_LWLOCK(49, WALSummarizer)
PG_LWLOCK(50, DSMRegistry)
PG_LWLOCK(51, InjectionPoint)
PG_LWLOCK(52, SerialControl)
PG_LWLOCK(53, WaitLSN)