public inbox for [email protected]
help / color / mirror / Atom feedFrom: Jingtang Zhang <[email protected]>
To: [email protected]
To: PostgreSQL-development <[email protected]>
Subject: Re: Optimize CPU usage of dropping buffers during recovery
Date: Sun, 1 Feb 2026 16:20:00 +0800
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>
A little bit modification for Perl test case and comments in v2 patch.
--
Regards, Jingtang
Attachments:
[application/octet-stream] v2-0001-Optimize-CPU-usage-of-dropping-buffers-during-recove.patch (4.1K, 2-v2-0001-Optimize-CPU-usage-of-dropping-buffers-during-recove.patch)
download | inline diff:
From 2d423d2b88e0f14a2fb51657ddfd93f7648598ca Mon Sep 17 00:00:00 2001
From: Jingtang Zhang <[email protected]>
Date: Sun, 1 Feb 2026 16:12:48 +0800
Subject: [PATCH] Optimize CPU usage of dropping buffers during recovery
Initialize cached nblocks to 0 when redo CREATE record.
---
src/backend/access/transam/xlogutils.c | 7 +++
src/backend/catalog/storage.c | 7 +++
src/test/recovery/t/060_truncate_empty.pl | 69 +++++++++++++++++++++++
3 files changed, 83 insertions(+)
create mode 100644 src/test/recovery/t/060_truncate_empty.pl
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index 5fbe39133b8..387c7621218 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -489,6 +489,13 @@ XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum,
*/
smgrcreate(smgr, forknum, true);
+ /*
+ * Invalidate the cache if the cached value is 0, and let smgrnblocks ask
+ * the kernel. The relation might be longer than the cached value due to
+ * relation extension before crash.
+ */
+ if (smgr->smgr_cached_nblocks[forknum] == 0)
+ smgr->smgr_cached_nblocks[forknum] = InvalidBlockNumber;
lastblock = smgrnblocks(smgr, forknum);
if (blkno < lastblock)
diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c
index e443a4993c5..859f515411a 100644
--- a/src/backend/catalog/storage.c
+++ b/src/backend/catalog/storage.c
@@ -993,6 +993,13 @@ smgr_redo(XLogReaderState *record)
reln = smgropen(xlrec->rlocator, INVALID_PROC_NUMBER);
smgrcreate(reln, xlrec->forkNum, true);
+
+ if (xlrec->forkNum == MAIN_FORKNUM)
+ {
+ reln->smgr_cached_nblocks[MAIN_FORKNUM] = 0;
+ reln->smgr_cached_nblocks[FSM_FORKNUM] = 0;
+ reln->smgr_cached_nblocks[VISIBILITYMAP_FORKNUM] = 0;
+ }
}
else if (info == XLOG_SMGR_TRUNCATE)
{
diff --git a/src/test/recovery/t/060_truncate_empty.pl b/src/test/recovery/t/060_truncate_empty.pl
new file mode 100644
index 00000000000..1956733f05f
--- /dev/null
+++ b/src/test/recovery/t/060_truncate_empty.pl
@@ -0,0 +1,69 @@
+use strict;
+use warnings FATAL => 'all';
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+use Time::HiRes qw(gettimeofday tv_interval);
+
+my $node = PostgreSQL::Test::Cluster->new('primary');
+$node->init();
+
+$node->append_conf('postgresql.conf', 'shared_buffers = 4GB');
+$node->append_conf('postgresql.conf', 'restart_after_crash = on');
+
+$node->start();
+
+$node->safe_psql('postgres',
+ q[CREATE TABLE test (id int);]);
+
+# SIGSTOP checkpointer and run some transactions
+my $checkpointer_pid = $node->safe_psql('postgres',
+ q[SELECT pid FROM pg_stat_activity WHERE backend_type = 'checkpointer';]);
+chomp($checkpointer_pid);
+kill 'STOP', $checkpointer_pid;
+note("Checkpointer stopped");
+
+$node->pgbench(
+ '--no-vacuum --client=10 --transactions=1000',
+ 0,
+ [qr{actually processed}],
+ [qr{^$}],
+ 'concurrent CREATE and DROP TABLE transactions',
+ {
+ 'truncate_empty_script' => q(
+ BEGIN;
+ INSERT INTO test VALUES (:client_id);
+ DELETE FROM test WHERE id = :client_id;
+ CREATE TABLE test_empty_:client_id (id int);
+ DROP TABLE test_empty_:client_id;
+ COMMIT;
+ )
+ });
+
+# stop the node in immediate mode for crash recovery
+$node->stop('immediate');
+
+my $recovery_start = [gettimeofday];
+$node->start();
+my $recovery_end = [gettimeofday];
+my $recovery_time = tv_interval($recovery_start, $recovery_end);
+
+note("Crash recovery time: ${recovery_time} seconds");
+
+my $log_content = $node->log_content();
+if ($log_content =~ /redo done at .+? system usage: CPU: user: ([\d.]+) s, system: ([\d.]+) s, elapsed: ([\d.]+) s/m)
+{
+ my $cpu_user = $1;
+ my $cpu_system = $2;
+ my $redo_elapsed = $3;
+
+ note("Redo elapsed time: $redo_elapsed s");
+ note(" CPU user: $cpu_user s, system: $cpu_system s");
+}
+
+# consistency check
+my $result = $node->safe_psql('postgres', q[SELECT COUNT(*) FROM test;]);
+is($result, '0', 'test table is empty after recovery');
+
+$node->stop();
+done_testing();
--
2.50.1 (Apple Git-155)
view thread (2+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected]
Subject: Re: Optimize CPU usage of dropping buffers during recovery
In-Reply-To: <[email protected]>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox