diff options
author | Heikki Linnakangas | 2023-11-27 15:42:39 +0000 |
---|---|---|
committer | Heikki Linnakangas | 2023-11-27 15:42:39 +0000 |
commit | 1f395354d8742d57c166104874114b6e0d01e104 (patch) | |
tree | 6a607b78be1c7e7b6dc812f1dba2a355110eef6a /src | |
parent | 360392fa2a9bb74338b4864790d18eadb13fd8a8 (diff) |
Reduce rate of walwriter wakeups due to async commits.
XLogSetAsyncXactLSN(), called at asynchronous commit, would wake up
walwriter every time the LSN advances, but walwriter doesn't actually
do anything unless it has at least 'wal_writer_flush_after' full
blocks of WAL to write. Repeatedly waking up walwriter to do nothing
is a waste of CPU cycles in both walwriter and the backends doing the
wakeups. To fix, apply the same logic in XLogSetAsyncXactLSN() to
decide whether to wake up walwriter, as walwriter uses to determine if
it has any work to do.
In the passing, rename misleadingly named 'flushbytes' local variable
to 'flushblocks'.
Author: Andres Freund, Heikki Linnakangas
Discussion: https://www.postgresql.org/message-id/20231024230929.vsc342baqs7kmbte@awork3.anarazel.de
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/transam/xlog.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index ef9b8e4fb96..1952b013fb4 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -2456,35 +2456,44 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN) { XLogRecPtr WriteRqstPtr = asyncXactLSN; bool sleeping; + bool wakeup = false; + XLogRecPtr prevAsyncXactLSN; SpinLockAcquire(&XLogCtl->info_lck); LogwrtResult = XLogCtl->LogwrtResult; sleeping = XLogCtl->WalWriterSleeping; + prevAsyncXactLSN = XLogCtl->asyncXactLSN; if (XLogCtl->asyncXactLSN < asyncXactLSN) XLogCtl->asyncXactLSN = asyncXactLSN; SpinLockRelease(&XLogCtl->info_lck); /* - * If the WALWriter is sleeping, we should kick it to make it come out of - * low-power mode. Otherwise, determine whether there's a full page of - * WAL available to write. + * If somebody else already called this function with a more aggressive + * LSN, they will have done what we needed (and perhaps more). */ - if (!sleeping) + if (asyncXactLSN <= prevAsyncXactLSN) + return; + + /* + * If the WALWriter is sleeping, kick it to make it come out of low-power + * mode, so that this async commit will reach disk within the expected + * amount of time. Otherwise, determine whether it has enough WAL + * available to flush, the same way that XLogBackgroundFlush() does. + */ + if (sleeping) + wakeup = true; + else { - /* back off to last completed page boundary */ - WriteRqstPtr -= WriteRqstPtr % XLOG_BLCKSZ; + int flushblocks; - /* if we have already flushed that far, we're done */ - if (WriteRqstPtr <= LogwrtResult.Flush) - return; + flushblocks = + WriteRqstPtr / XLOG_BLCKSZ - LogwrtResult.Flush / XLOG_BLCKSZ; + + if (WalWriterFlushAfter == 0 || flushblocks >= WalWriterFlushAfter) + wakeup = true; } - /* - * Nudge the WALWriter: it has a full page of WAL to write, or we want it - * to come out of low-power mode so that this async commit will reach disk - * within the expected amount of time. - */ - if (ProcGlobal->walwriterLatch) + if (wakeup && ProcGlobal->walwriterLatch) SetLatch(ProcGlobal->walwriterLatch); } @@ -2803,7 +2812,7 @@ XLogBackgroundFlush(void) bool flexible = true; static TimestampTz lastflush; TimestampTz now; - int flushbytes; + int flushblocks; TimeLineID insertTLI; /* XLOG doesn't need flushing during recovery */ @@ -2855,9 +2864,13 @@ XLogBackgroundFlush(void) /* * Determine how far to flush WAL, based on the wal_writer_delay and * wal_writer_flush_after GUCs. + * + * Note that XLogSetAsyncXactLSN() performs similar calculation based on + * wal_writer_flush_after, to decide when to wake us up. Make sure the + * logic is the same in both places if you change this. */ now = GetCurrentTimestamp(); - flushbytes = + flushblocks = WriteRqst.Write / XLOG_BLCKSZ - LogwrtResult.Flush / XLOG_BLCKSZ; if (WalWriterFlushAfter == 0 || lastflush == 0) @@ -2876,7 +2889,7 @@ XLogBackgroundFlush(void) WriteRqst.Flush = WriteRqst.Write; lastflush = now; } - else if (flushbytes >= WalWriterFlushAfter) + else if (flushblocks >= WalWriterFlushAfter) { /* exceeded wal_writer_flush_after blocks, flush */ WriteRqst.Flush = WriteRqst.Write; |