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 1tYjW9-00EEvg-7q for pgsql-hackers@arkaria.postgresql.org; Fri, 17 Jan 2025 10:23:57 +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 1tYjW6-00D8kn-TD for pgsql-hackers@arkaria.postgresql.org; Fri, 17 Jan 2025 10:23:55 +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 1tYjW6-00D8kZ-FT for pgsql-hackers@lists.postgresql.org; Fri, 17 Jan 2025 10:23:55 +0000 Received: from mail-wm1-x32e.google.com ([2a00:1450:4864:20::32e]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1tYjW4-0000Zs-1L for pgsql-hackers@lists.postgresql.org; Fri, 17 Jan 2025 10:23:53 +0000 Received: by mail-wm1-x32e.google.com with SMTP id 5b1f17b1804b1-4361f664af5so20507705e9.1 for ; Fri, 17 Jan 2025 02:23:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1737109431; x=1737714231; darn=lists.postgresql.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=u9pYUT+1NGEcc33puu5B4kXBkklpgK/iPFi48BpAwHo=; b=QaYaY2YJ2/FzyMD/x4H1JWtD9h2hXOm6fL0C4bb6lEh4Iewhj/RPsQbvFnP/XzhRoU nEe92ANR0VVAfyD1zN5/QVwv8wKManKsi25PUPCUrLipzdZ9guYweFedzxWNfCcFhTKt aUYLMusIj9AnmTYyv1dj5YhDMKKTg+Rr+E7LMNF7BmHlyd+r2MFocI6ZRVhL5TXKvXw6 nI1Q86ffUNUiNaWqr3bPoX8R2PqZRqbWIEdKSTCMaK/l69dMzJtoyNHWUhgB61/72/Uw SYVvPsVj9idMBNLkxSjCROHsjrJd2JJTgaDRQWFIO7Lcwu77iXxEIM2fkJTtvBUqOMN9 7tZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1737109431; x=1737714231; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=u9pYUT+1NGEcc33puu5B4kXBkklpgK/iPFi48BpAwHo=; b=JX9wIekGSw+ZfBYz+SYhaRD16pQ97empW1Hm2x7v0d1VGhM9dZTYcc2re7MZZUp2Ll ferBkPAiavj1mm/lf3J9+ifcugfI02FaQGdAxOWiXZee/wgLvzvTehJcmXe/el9isOem e1OJmg1qVqyZB6fV+qEfe2Z6AC9ck8QfiiqH057M8l5m1ARhZSzNJb7hHuYuaJiqwAr3 VI0OZ+BjTnM6QDqxZzyshiBUYOVl9LVK3iCFeWYK6rumSFGmKaKHSlFRF4iDVaMVhb75 0fNWZqXQr2TyfVWOagxYlKAEGq9MuBm5ujWbMgsgg0U3eV7U5YFKs/lz8tlCjxetySaA 4B3g== X-Forwarded-Encrypted: i=1; AJvYcCW7axYP5BOO7qVtMvOmtACmm9m4thqzSP9VlCpHmO+vvbTshXrqBQLskuLDdBX9zuXee+d82ibgBIJgOWNa@lists.postgresql.org X-Gm-Message-State: AOJu0YyDpTXrwnwFWwCB7GoRY12ffFza0RQQVGzchGFLA0FEYsxaKe36 FdA0GpapzfH6c5vNtpd+/yLZ6ng3jA9LAwBIhj732rmbev4rosVR X-Gm-Gg: ASbGnctsj+Auw076tiSUsdC1vVOOum+BVIWSiTqFTpWIa6MnARbC2VaHi0XeuEK/V0a qg5YmkGyE9wd6xNy9gK63OG42br3xtRlBO7CVLHOxTomY8LMR7fPLjNSFnsORPyMrBMUIeV8yyg yJnyqeMmf7gaku/paPTw3B2AyKv6F3iIP8d64Ucbqe2KKL9I3kMTrwzPGgacPpIwMLNDiE2LxTr MtidfK4LDBCGrc2DDul7QmcEZ7GSTBF1o6fw1WGYr1k1gGNFgv3Qv1wO2tTB6Iafkb18fm4bgtk raMpiToBQlwhkKk068aeLobspfHPw3mOXFXv/QntRQNoHeYNqyErANjzTDeWB/ji97VUcnGnPnX LknyMn2I= X-Google-Smtp-Source: AGHT+IGFM+glY7erSrBEUI5lXxJaeiloWWBe6MGeNkb33pq8INf58VYAKejRi/SdUbsQaF+smL4P7w== X-Received: by 2002:a05:600c:4c86:b0:436:6ddf:7a27 with SMTP id 5b1f17b1804b1-4389141c412mr19465845e9.23.1737109431127; Fri, 17 Jan 2025 02:23:51 -0800 (PST) Received: from ip-10-97-1-34.eu-west-3.compute.internal (ec2-15-236-134-5.eu-west-3.compute.amazonaws.com. [15.236.134.5]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-438904621cdsm28843265e9.27.2025.01.17.02.23.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 17 Jan 2025 02:23:50 -0800 (PST) Date: Fri, 17 Jan 2025 10:23:48 +0000 From: Bertrand Drouvot To: Michael Paquier Cc: Andres Freund , Nazir Bilal Yavuz , Alvaro Herrera , Kyotaro Horiguchi , pgsql-hackers@lists.postgresql.org Subject: Re: per backend I/O statistics Message-ID: References: <66efowskppsns35v5u2m7k4sdnl7yoz5bo64tdjwq7r5lhplrz@y7dme5xwh2r5> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="ubo7LhbbFKyqXJ/R" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --ubo7LhbbFKyqXJ/R Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, On Fri, Jan 17, 2025 at 03:12:36PM +0900, Michael Paquier wrote: > On Fri, Jan 17, 2025 at 06:06:35AM +0000, Bertrand Drouvot wrote: > > On Fri, Jan 17, 2025 at 09:08:02AM +0900, Michael Paquier wrote: > >> I could tweak that around the beginning of next week with a proposal > >> of patch. Bertrand, perhaps you'd prefer hack on this one? > > > > Yeah, I had in mind to work on it (in the exact same line as you are describing > > above). I'll work on it. Please find attached a patch implementing the ideas above, meaning: - It creates a new PendingBackendStats variable - It uses this variable to increment and flush per backend pending IO statistics That way we get rid of the memory allocation for pending IO statistics. One remark: a special case has been added in pgstat_flush_pending_entries(). The reason is that while the per backend stats are "variable-numbered" stats, it could be that their pending stats are not part of pgStatPending. This is currently the case (with this patch) as the per backend pending IO stats are not tracked with pgstat_prep_backend_pending() and friends anymore. Thoughts? Regards, -- Bertrand Drouvot PostgreSQL Contributors Team RDS Open Source Databases Amazon Web Services: https://aws.amazon.com --ubo7LhbbFKyqXJ/R Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v1-0001-Rework-per-backend-pending-stats.patch" From 48d715a4a8b667628bb8ccf573e0003eb8f54633 Mon Sep 17 00:00:00 2001 From: Bertrand Drouvot Date: Fri, 17 Jan 2025 06:44:47 +0000 Subject: [PATCH v1] Rework per backend pending stats 9aea73fc61d added per backend pending statistics but not all of them are well suited to memory allocation and have to be outside of critical sections. For those (the only current one is I/O statistics but WAL statistics is under discussion), let's rely on a new PendingBackendStats instead. --- src/backend/utils/activity/pgstat.c | 27 ++++++++++++++++++- src/backend/utils/activity/pgstat_backend.c | 29 +++++++++++++++------ src/backend/utils/activity/pgstat_io.c | 14 +++------- src/include/pgstat.h | 12 +++++++++ 4 files changed, 62 insertions(+), 20 deletions(-) 89.0% src/backend/utils/activity/ 10.9% src/include/ diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c index 34520535d54..27aa0491001 100644 --- a/src/backend/utils/activity/pgstat.c +++ b/src/backend/utils/activity/pgstat.c @@ -1369,6 +1369,7 @@ static bool pgstat_flush_pending_entries(bool nowait) { bool have_pending = false; + bool backend_have_pending = false; dlist_node *cur = NULL; /* @@ -1416,9 +1417,33 @@ pgstat_flush_pending_entries(bool nowait) cur = next; } + /* + * There is a special case for some pending stats that are tracked in + * PendingBackendStats. It's possible that those have not been flushed + * above, hence the extra check here. + */ + if (!pg_memory_is_all_zeros(&PendingBackendStats, + sizeof(struct PgStat_BackendPending))) + { + PgStat_EntryRef *entry_ref; + + entry_ref = pgstat_get_entry_ref(PGSTAT_KIND_BACKEND, InvalidOid, + MyProcNumber, false, NULL); + + if (entry_ref) + { + PgStat_HashKey key = entry_ref->shared_entry->key; + PgStat_Kind kind = key.kind; + const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind); + + if (!kind_info->flush_pending_cb(entry_ref, nowait)) + backend_have_pending = true; + } + } + Assert(dlist_is_empty(&pgStatPending) == !have_pending); - return have_pending; + return (have_pending || backend_have_pending); } diff --git a/src/backend/utils/activity/pgstat_backend.c b/src/backend/utils/activity/pgstat_backend.c index 79e4d0a3053..ca5cec348b2 100644 --- a/src/backend/utils/activity/pgstat_backend.c +++ b/src/backend/utils/activity/pgstat_backend.c @@ -22,8 +22,11 @@ #include "postgres.h" +#include "utils/memutils.h" #include "utils/pgstat_internal.h" +PgStat_BackendPending PendingBackendStats = {0}; + /* * Returns statistics of a backend by proc number. */ @@ -46,14 +49,20 @@ static void pgstat_flush_backend_entry_io(PgStat_EntryRef *entry_ref) { PgStatShared_Backend *shbackendent; - PgStat_BackendPending *pendingent; PgStat_BktypeIO *bktype_shstats; - PgStat_PendingIO *pending_io; + PgStat_PendingIO pending_io; + + /* + * This function can be called even if nothing at all has happened. In + * this case, avoid unnecessarily modifying the stats entry. + */ + if (pg_memory_is_all_zeros(&PendingBackendStats.pending_io, + sizeof(struct PgStat_PendingIO))) + return; shbackendent = (PgStatShared_Backend *) entry_ref->shared_stats; - pendingent = (PgStat_BackendPending *) entry_ref->pending; bktype_shstats = &shbackendent->stats.io_stats; - pending_io = &pendingent->pending_io; + pending_io = PendingBackendStats.pending_io; for (int io_object = 0; io_object < IOOBJECT_NUM_TYPES; io_object++) { @@ -64,17 +73,21 @@ pgstat_flush_backend_entry_io(PgStat_EntryRef *entry_ref) instr_time time; bktype_shstats->counts[io_object][io_context][io_op] += - pending_io->counts[io_object][io_context][io_op]; + pending_io.counts[io_object][io_context][io_op]; bktype_shstats->bytes[io_object][io_context][io_op] += - pending_io->bytes[io_object][io_context][io_op]; - - time = pending_io->pending_times[io_object][io_context][io_op]; + pending_io.bytes[io_object][io_context][io_op]; + time = pending_io.pending_times[io_object][io_context][io_op]; bktype_shstats->times[io_object][io_context][io_op] += INSTR_TIME_GET_MICROSEC(time); } } } + + /* + * Clear out the statistics buffer, so it can be re-used. + */ + MemSet(&PendingBackendStats.pending_io, 0, sizeof(PgStat_PendingIO)); } /* diff --git a/src/backend/utils/activity/pgstat_io.c b/src/backend/utils/activity/pgstat_io.c index 027aad8b24e..b8f19515ae1 100644 --- a/src/backend/utils/activity/pgstat_io.c +++ b/src/backend/utils/activity/pgstat_io.c @@ -75,11 +75,8 @@ pgstat_count_io_op(IOObject io_object, IOContext io_context, IOOp io_op, if (pgstat_tracks_backend_bktype(MyBackendType)) { - PgStat_BackendPending *entry_ref; - - entry_ref = pgstat_prep_backend_pending(MyProcNumber); - entry_ref->pending_io.counts[io_object][io_context][io_op] += cnt; - entry_ref->pending_io.bytes[io_object][io_context][io_op] += bytes; + PendingBackendStats.pending_io.counts[io_object][io_context][io_op] += cnt; + PendingBackendStats.pending_io.bytes[io_object][io_context][io_op] += bytes; } PendingIOStats.counts[io_object][io_context][io_op] += cnt; @@ -146,13 +143,8 @@ pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, io_time); if (pgstat_tracks_backend_bktype(MyBackendType)) - { - PgStat_BackendPending *entry_ref; - - entry_ref = pgstat_prep_backend_pending(MyProcNumber); - INSTR_TIME_ADD(entry_ref->pending_io.pending_times[io_object][io_context][io_op], + INSTR_TIME_ADD(PendingBackendStats.pending_io.pending_times[io_object][io_context][io_op], io_time); - } } pgstat_count_io_op(io_object, io_context, io_op, cnt, bytes); diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 2d40fe3e70f..3eb7b6614fe 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -826,5 +826,17 @@ extern PGDLLIMPORT SessionEndType pgStatSessionEndCause; /* updated directly by backends and background processes */ extern PGDLLIMPORT PgStat_PendingWalStats PendingWalStats; +/* + * Variables in pgstat_backend.c + */ + +/* updated directly by backends */ + +/* + * Some pending statistics are not well suited to memory allocation and have + * to be outside of critical sections. For those, let's rely on this variable + * instead. + */ +extern PGDLLIMPORT PgStat_BackendPending PendingBackendStats; #endif /* PGSTAT_H */ -- 2.34.1 --ubo7LhbbFKyqXJ/R--