Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pwSby-0000LH-2p for pgsql-hackers@arkaria.postgresql.org; Tue, 09 May 2023 19:02:58 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pwSbw-0005DJ-FR for pgsql-hackers@arkaria.postgresql.org; Tue, 09 May 2023 19:02:56 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pwSbu-0005DA-N8 for pgsql-hackers@lists.postgresql.org; Tue, 09 May 2023 19:02:56 +0000 Received: from out2-smtp.messagingengine.com ([66.111.4.26]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1pwSbq-001QoH-P4 for pgsql-hackers@postgresql.org; Tue, 09 May 2023 19:02:53 +0000 Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id AB8A15C024D; Tue, 9 May 2023 15:02:49 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Tue, 09 May 2023 15:02:49 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=anarazel.de; h= cc:cc:content-type:content-type:date:date:from:from:in-reply-to :message-id:mime-version:reply-to:sender:subject:subject:to:to; s=fm3; t=1683658969; x=1683745369; bh=Kjkg6C4+kfgMR475xQt6ZoKxc cM7xo2/NfFrebJQwKU=; b=E/L5qzPJREUPJAZURzQr5svjtHVehDURGMDdXQJEG jTePpfQ0qOVx/xo5fs499plXwWadaqOZA+QuzgkSmjE4RNYD/2P59IImQTGvAGPw BC8F/GeMKVfWJ/IuBZBib3dZ6NW5nJxyd1oXaH/c4+miL6/qFP3ljSi1+NIMC7hw 7Ly38ScJO81SwJbtanQRzD27F+9Fx1p00OVv19CMmLirhwNk6IixCh8tRwI3wEhR Pt3vXDCO9hQ6RIz6rrtL18HVtJO/idWqE98WTX+I1HS2D5MInpRMj0GVPHlFjZsm gNarHsvRl9Jm832V6Ru9RAsHPr9QVzr3RwSFVc95zKsyA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:message-id :mime-version:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1683658969; x=1683745369; bh=Kjkg6C4+kfgMR475xQt6ZoKxccM7xo2/NfF rebJQwKU=; b=YkIdrM/mZX6URLRty0oKvOYjNbDHR8cSw4JyuM+puL4GzcqfY+S Yx1HQrsLSYypmgJFaUpJJObOEjTbRXTNKXBLssncmInlhRCwwnqvwPeJjwockfcX G+/Y7Z7o45IobUECh8rISdlpVkh0USQXExuY5sfB3uMm3dxTMFLSbtkiHk7IuWpm 7Hpl+AYjsrpgOOCfX0DAXNpbukR+rUEQsWBMRNxbBDMTFoWgTJwhCi4wGzljwDlJ 7kzjF7eZW+JKLxunUPoHkY+SX4uilQ33g5ur2i17wxD5LkKWggysMqzErS5GQW7G yThtNzt74zDsVKDCZ6Mn4hxaqyPyTzq6Xbg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrfeeguddgheekucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepfffhvfevuffkgggtugesthdtredttddtvdenucfhrhhomheptehnughrvghs ucfhrhgvuhhnugcuoegrnhgurhgvshesrghnrghrrgiivghlrdguvgeqnecuggftrfgrth htvghrnhepfeffveduueehfedtuefhkeetgeeuvdeuleeujedvjeekieefueeugfekvdfg veehnecuffhomhgrihhnpehpohhsthhgrhdrvghsnecuvehluhhsthgvrhfuihiivgeptd enucfrrghrrghmpehmrghilhhfrhhomheprghnughrvghssegrnhgrrhgriigvlhdruggv X-ME-Proxy: Feedback-ID: id4a34324:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 9 May 2023 15:02:48 -0400 (EDT) Date: Tue, 9 May 2023 12:02:47 -0700 From: Andres Freund To: pgsql-hackers@postgresql.org, "Drouvot, Bertrand" , Jeff Davis , Amit Kapila Cc: Robert Haas , Masahiko Sawada Subject: walsender performance regression due to logical decoding on standby changes Message-ID: <20230509190247.3rrplhdgem6su6cg@awork3.anarazel.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi, Unfortunately I have found the following commit to have caused a performance regression: commit e101dfac3a53c20bfbf1ca85d30a368c2954facf Author: Andres Freund Date: 2023-04-08 00:24:24 -0700 For cascading replication, wake physical and logical walsenders separately Physical walsenders can't send data until it's been flushed; logical walsenders can't decode and send data until it's been applied. On the standby, the WAL is flushed first, which will only wake up physical walsenders; and then applied, which will only wake up logical walsenders. Previously, all walsenders were awakened when the WAL was flushed. That was fine for logical walsenders on the primary; but on the standby the flushed WAL would have been not applied yet, so logical walsenders were awakened too early. Per idea from Jeff Davis and Amit Kapila. Author: "Drouvot, Bertrand" Reviewed-By: Jeff Davis Reviewed-By: Robert Haas Reviewed-by: Amit Kapila Reviewed-by: Masahiko Sawada Discussion: https://postgr.es/m/CAA4eK1+zO5LUeisabX10c81LU-fWMKO4M9Wyg1cdkbW7Hqh6vQ@mail.gmail.com The problem is that, on a standby, after the change - as needed to for the approach to work - the call to WalSndWakeup() in ApplyWalRecord() happens for every record, instead of only happening when the timeline is changed (or WAL is flushed or ...). WalSndWakeup() iterates over all walsender slots, regardless of whether in use. For each of the walsender slots it acquires a spinlock. When replaying a lot of small-ish WAL records I found the startup process to spend the majority of the time in WalSndWakeup(). I've not measured it very precisely yet, but the overhead is significant (~35% slowdown), even with the default max_wal_senders. If that's increased substantially, it obviously gets worse. The only saving grace is that this is not an issue on the primary. I unfortunately spent less time on this commit of the logical-decoding-on-standby series than on the others. There were so many other senior contributors discussing it, that I "relaxed" a bit too much. I don't think the approach of not having any sort of "registry" of whether anybody is waiting for the replay position to be updated is feasible. Iterating over all walsenders slots is just too expensive - WalSndWakeup() shows up even if I remove the spinlock (which we likely could, especially when just checking if the the walsender is connected). My current guess is that mis-using a condition variable is the best bet. I think it should work to use ConditionVariablePrepareToSleep() before a WalSndWait(), and then ConditionVariableCancelSleep(). I.e. to never use ConditionVariableSleep(). The latch set from ConditionVariableBroadcast() would still cause the necessary wakeup. Greetings, Andres Freund