v1-0001-Reduce-power-consumption-by-WAL-writer.patch
application/octet-stream
Filename: v1-0001-Reduce-power-consumption-by-WAL-writer.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v1-0001
Subject: Reduce power consumption by WAL writer
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 55 | 0 |
| src/backend/access/transam/xloginsert.c | 6 | 0 |
| src/backend/postmaster/walwriter.c | 13 | 7 |
| src/include/access/xlog.h | 1 | 0 |
From da223287c12d0077951a00f2be7eff9cdc6ae880 Mon Sep 17 00:00:00 2001
From: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Date: Tue, 31 Jan 2023 08:23:51 +0000
Subject: [PATCH v1] Reduce power consumption by WAL writer
---
src/backend/access/transam/xlog.c | 55 +++++++++++++++++++++++++
src/backend/access/transam/xloginsert.c | 6 +++
src/backend/postmaster/walwriter.c | 20 +++++----
src/include/access/xlog.h | 1 +
4 files changed, 75 insertions(+), 7 deletions(-)
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index fb4c860bde..918f3959d3 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -2393,6 +2393,61 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
SetLatch(ProcGlobal->walwriterLatch);
}
+/*
+ * Wake up WAL writer process to write and flush newly generated WAL.
+ *
+ * This function better be in walwriter.c, but it reads LogwrtResult, a static
+ * variable from xlog.c. Hence we choose to keep it here for the sake of
+ * simplicity.
+ */
+void
+WakeupWALWriter(void)
+{
+ XLogRecPtr WriteRqstPtr = XactLastRecEnd;
+
+ /* back off to last completed page boundary */
+ WriteRqstPtr -= WriteRqstPtr % XLOG_BLCKSZ;
+
+ /*
+ * Let's not nudge WAL writer if somebody (this backend itself in
+ * XLogInsertRecord() or other backend or WAL writer itself in the ongoing
+ * run) already flushed that far. This avoids unnecessary WAL writer
+ * wakeups.
+ *
+ * It's possible that LogwrtResult is older, in which case, we nudge the
+ * WAL writer and it may do nothing. This is okay than to make this
+ * function costly by acquiring info_lck and read LogwrtResult freshly.
+ */
+ if (WriteRqstPtr <= LogwrtResult.Flush)
+ return;
+
+ /*
+ * XXXX: While more number of nudges/SetLatch() calls reduce the amount of
+ * WAL that this backend needs to write/flsuh, it might burden the WAL
+ * writer too much.
+ *
+ * To reduce the number of nudges, we can do all or some of the following
+ * things:
+ *
+ * 1) Nudge only when WAL writer is sleeping (use WalWriterSleeping).
+ *
+ * 2) Nudge only after wal_writer_delay has elapsed since the last nudge.
+ *
+ * 3) Nudge only after this backend has generated a configurable amount of
+ * WAL. Introduce a new GUC for this purpose wal_writer_wakeup_after
+ * (Amount of WAL written out by a backend that wakes up WAL writer to
+ * help write and flush WAL). Or use existing GUC
+ * wal_writer_flush_after.
+ */
+
+ /*
+ * Nudge WAL writer. Even if WAL writer is woken up, it does its work only
+ * when necessary at its own pace, see XLogBackgroundFlush() for details.
+ */
+ if (ProcGlobal->walwriterLatch)
+ SetLatch(ProcGlobal->walwriterLatch);
+}
+
/*
* Record the LSN up to which we can remove WAL because it's not required by
* any replication slot.
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index 008612e032..3d7dfec3ba 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -503,6 +503,12 @@ XLogInsert(RmgrId rmid, uint8 info)
XLogResetInsertion();
+ /*
+ * XXX: Effects of calling WakeupWALWriter() in XLogInsert() needs to be
+ * measured, say with high-write workload.
+ */
+ WakeupWALWriter();
+
return EndPos;
}
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 3113e8fbdd..9e30679cdc 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -71,12 +71,10 @@ int WalWriterDelay = 200;
int WalWriterFlushAfter = 128;
/*
- * Number of do-nothing loops before lengthening the delay time, and the
- * multiplier to apply to WalWriterDelay when we do decide to hibernate.
+ * Number of do-nothing loops before lengthening the delay time.
* (Perhaps these need to be configurable?)
*/
#define LOOPS_UNTIL_HIBERNATE 50
-#define HIBERNATE_FACTOR 25
/* Prototypes for private functions */
static void HandleWalWriterInterrupts(void);
@@ -226,6 +224,7 @@ WalWriterMain(void)
for (;;)
{
long cur_timeout;
+ int wakeEvents;
/*
* Advertise whether we might hibernate in this cycle. We do this
@@ -262,16 +261,23 @@ WalWriterMain(void)
/*
* Sleep until we are signaled or WalWriterDelay has elapsed. If we
- * haven't done anything useful for quite some time, lengthen the
- * sleep time so as to reduce the server's idle power consumption.
+ * haven't done anything useful for quite some time, sleep until an
+ * event occurs so as to reduce the server's idle power consumption.
*/
if (left_till_hibernate > 0)
+ {
cur_timeout = WalWriterDelay; /* in ms */
+ wakeEvents = WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH;
+ }
else
- cur_timeout = WalWriterDelay * HIBERNATE_FACTOR;
+ {
+ Assert(hibernating == true);
+ cur_timeout = -1L;
+ wakeEvents = WL_LATCH_SET | WL_EXIT_ON_PM_DEATH;
+ }
(void) WaitLatch(MyLatch,
- WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
+ wakeEvents,
cur_timeout,
WAIT_EVENT_WAL_WRITER_MAIN);
}
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index cfe5409738..f30decfb7a 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -207,6 +207,7 @@ extern int XLogFileOpen(XLogSegNo segno, TimeLineID tli);
extern void CheckXLogRemoved(XLogSegNo segno, TimeLineID tli);
extern XLogSegNo XLogGetLastRemovedSegno(void);
extern void XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN);
+extern void WakeupWALWriter(void);
extern void XLogSetReplicationSlotMinimumLSN(XLogRecPtr lsn);
extern void xlog_redo(struct XLogReaderState *record);
--
2.34.1