Use an LWLock instead of a spinlock in waitlsn.c
authorAlexander Korotkov <akorotkov@postgresql.org>
Sat, 6 Apr 2024 21:31:43 +0000 (00:31 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
Sat, 6 Apr 2024 21:49:53 +0000 (00:49 +0300)
This should prevent busy-waiting when number of waiting processes is high.

Discussion: https://postgr.es/m/202404030658.hhj3vfxeyhft%40alvherre.pgsql
Author: Alvaro Herrera

src/backend/commands/waitlsn.c
src/backend/utils/activity/wait_event_names.txt
src/include/commands/waitlsn.h
src/include/storage/lwlocklist.h

index 51a34d422e237d4eab5b12ceaf124b0d8b900d19..a57b818a2d482dd633deb085c50d394a09fdbb6a 100644 (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
index 39a1c40d76cc705788ba494a1c33409d933ec5ab..5f2fa814c8eec90a8b043b2c64bcde5bdc87c8c3 100644 (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)
index 0d80248682ccb5cb85b867b6771d9eb9228a363d..b3d9eed64d816cfd0abc68708ba3317c3c2a9d6e 100644 (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;
index 85f6568b9e4c227ec7deac5d3206cd115a63c73c..c2bab5a794e09544d09b2b745adfb75264856d0f 100644 (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)