Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rs3tt-004Z4h-Dl for pgsql-hackers@arkaria.postgresql.org; Wed, 03 Apr 2024 16:55:50 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rs3tr-004txY-3f for pgsql-hackers@arkaria.postgresql.org; Wed, 03 Apr 2024 16:55:47 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rs3tq-004txP-Cm for pgsql-hackers@lists.postgresql.org; Wed, 03 Apr 2024 16:55:46 +0000 Received: from wfhigh4-smtp.messagingengine.com ([64.147.123.155]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rs3tn-000O9F-FB for pgsql-hackers@lists.postgresql.org; Wed, 03 Apr 2024 16:55:45 +0000 Received: from compute7.internal (compute7.nyi.internal [10.202.2.48]) by mailfhigh.west.internal (Postfix) with ESMTP id BA80318000AB; Wed, 3 Apr 2024 12:55:40 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute7.internal (MEProxy); Wed, 03 Apr 2024 12:55:41 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :reply-to:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t=1712163340; x= 1712249740; bh=SMnSzKIB0ABg1MQn4T34m0GWm0HEpxz9h5UjALzgEN8=; b=Y LKwsCgc09iGWoi4J6dBGtnjeBXrg/foDwarymWuRQrst1dhjrs9z6KRSqGM5oHn2 mVmYbtZLecJjRQi0RSk6r7+ovnrbTDMFDjy+GK5BDqSRILJ/Ka280QKNlQnrCExf jZCR+k/z2rr2WvjbBTAD/36cqQjJSaUyZDu3uc5iZTxvaDNCJO31mg6JZJxE4/xA emYZTh01uBm9x4LICVAWwVIffnUFY9iPfiVGQ1wUQCbRUL8hjBFWbjKMfBvxxRV/ dsNxMALb+wFtYWLe624Wqa4pQungJ8R7KHJLttpTle8amfVaFFfpKBuvs0vrePO2 kGewlhbTvXDZujur6CeDA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvledrudefiedgieefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkgggtugfgjgesmhekreertddtjeenucfhrhhomheptehlvhgr rhhoucfjvghrrhgvrhgruceorghlvhhhvghrrhgvsegrlhhvhhdrnhhoqdhiphdrohhrgh eqnecuggftrfgrthhtvghrnhepudelkeekgfdttdettdekgfduvdeiffelteegjeeihfet heekveeftedtuddvhfeunecuffhomhgrihhnpegvnhhtvghrphhrihhsvggusgdrtghomh enucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrlhhv hhgvrhhrvgesrghlvhhhrdhnohdqihhprdhorhhg X-ME-Proxy: Feedback-ID: ia2694551:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 3 Apr 2024 12:55:38 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alvh.no-ip.org; s=schmee; t=1712163336; bh=wiLEJFfbUMSffiLd2/XM7CNmBKb0r8KVKaB8ryWVamA=; h=Date:From:To:Cc:Subject:In-Reply-To:From; b=Rm7+gvqGxuTFXHqUisI3p3C+wNjs6NxxqlYqPGd5hYjTVoFzWRF5NSRo0JOsVFVK7 R0QZIa+hAhJX+d6ddk/Wo+qw/z1e80fe0us6TIuMPuIEd5oXK5a0j1FQaT3bH3qAcB lu7knaI+c7Bt6VXZSwL39wNeXSXgXZzbt+hdfIMwkzaX1o7h18ngaq1mXAWxPp9YbB sJWQku0Nz1FODwg52I4r1rOiJAUTk1ZfAq2OYfXWkff4EYA3cBbRMTjKe6S1TbuBG6 kKL49XGslofT9KUHVt56N3o6KfWVtIvpZHHm7e07GA3nJKMhlAOylhoAhQU/ER4vOf TO+/fdqZc8TEQ== Received: by schmee.alvh.no-ip.org (Postfix, from userid 1000) id 0752841E; Wed, 3 Apr 2024 18:55:35 +0200 (CEST) Date: Wed, 3 Apr 2024 18:55:35 +0200 From: Alvaro Herrera To: Alexander Korotkov Cc: Bharath Rupireddy , Kartyshov Ivan , Euler Taveira , Thomas Munro , Peter Eisentraut , Amit Kapila , Dilip Kumar , Peter Smith , pgsql-hackers@lists.postgresql.org Subject: Re: [HACKERS] make async slave to wait for lsn to be replayed Message-ID: <202404031655.u2hsgajymabj@alvherre.pgsql> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="zkso4zniwuqxsgxb" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --zkso4zniwuqxsgxb Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit Hello Alexander, On 2024-Apr-03, Alexander Korotkov wrote: > Regarding the shmem data structure for LSN waiters. I didn't pick > LWLock or ConditionVariable, because I needed the ability to wake up > only those waiters whose LSN is already replayed. In my experience > waking up a process is way slower than scanning a short flat array. I agree, but I think that's unrelated to what I was saying, which is just the patch I attach here. > However, I agree that when the number of waiters is very high and flat > array may become a problem. It seems that the pairing heap is not > hard to use for shmem structures. The only memory allocation call in > paritingheap.c is in pairingheap_allocate(). So, it's only needed to > be able to initialize the pairing heap in-place, and it will be fine > for shmem. Ok. With the code as it stands today, everything in WaitLSNState apart from the pairing heap is accessed without any locking. I think this is at least partly OK because each backend only accesses its own entry; but it deserves a comment. Or maybe something more, because WaitLSNSetLatches does modify the entry for other backends. (Admittedly, this could only happens for backends that are already sleeping, and it only happens with the lock acquired, so it's probably okay. But clearly it deserves a comment.) Don't we need to WaitLSNCleanup() during error recovery or something? -- Álvaro Herrera 48°01'N 7°57'E — https://www.EnterpriseDB.com/ "World domination is proceeding according to plan" (Andrew Morton) --zkso4zniwuqxsgxb Content-Type: text/x-diff; charset=utf-8 Content-Disposition: attachment; filename="0001-Use-an-LWLock-instead-of-a-spinlock-in-waitlsn.c.patch" From 4079dc6a6a6893055b32dee75f178b324bbaef77 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Wed, 3 Apr 2024 18:35:15 +0200 Subject: [PATCH] Use an LWLock instead of a spinlock in waitlsn.c --- src/backend/commands/waitlsn.c | 15 +++++++-------- src/backend/utils/activity/wait_event_names.txt | 1 + src/include/commands/waitlsn.h | 5 +---- src/include/storage/lwlocklist.h | 1 + 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/backend/commands/waitlsn.c b/src/backend/commands/waitlsn.c index 51a34d422e..a57b818a2d 100644 --- a/src/backend/commands/waitlsn.c +++ b/src/backend/commands/waitlsn.c @@ -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 diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt index 0d288d6b3d..ec43a78d60 100644 --- a/src/backend/utils/activity/wait_event_names.txt +++ b/src/backend/utils/activity/wait_event_names.txt @@ -330,6 +330,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 pg_serial state." +WaitLSN "Waiting to read or update shared Wait-for-LSN state." # # END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE) diff --git a/src/include/commands/waitlsn.h b/src/include/commands/waitlsn.h index 0d80248682..b3d9eed64d 100644 --- a/src/include/commands/waitlsn.h +++ b/src/include/commands/waitlsn.h @@ -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; diff --git a/src/include/storage/lwlocklist.h b/src/include/storage/lwlocklist.h index 85f6568b9e..c2bab5a794 100644 --- a/src/include/storage/lwlocklist.h +++ b/src/include/storage/lwlocklist.h @@ -83,3 +83,4 @@ PG_LWLOCK(49, WALSummarizer) PG_LWLOCK(50, DSMRegistry) PG_LWLOCK(51, InjectionPoint) PG_LWLOCK(52, SerialControl) +PG_LWLOCK(53, WaitLSN) -- 2.39.2 --zkso4zniwuqxsgxb--