Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1f39535

Browse files
committed
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
1 parent 360392f commit 1f39535

File tree

1 file changed

+31
-18
lines changed
  • src/backend/access/transam

1 file changed

+31
-18
lines changed

src/backend/access/transam/xlog.c

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2456,35 +2456,44 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
24562456
{
24572457
XLogRecPtr WriteRqstPtr = asyncXactLSN;
24582458
bool sleeping;
2459+
bool wakeup = false;
2460+
XLogRecPtr prevAsyncXactLSN;
24592461

24602462
SpinLockAcquire(&XLogCtl->info_lck);
24612463
LogwrtResult = XLogCtl->LogwrtResult;
24622464
sleeping = XLogCtl->WalWriterSleeping;
2465+
prevAsyncXactLSN = XLogCtl->asyncXactLSN;
24632466
if (XLogCtl->asyncXactLSN < asyncXactLSN)
24642467
XLogCtl->asyncXactLSN = asyncXactLSN;
24652468
SpinLockRelease(&XLogCtl->info_lck);
24662469

24672470
/*
2468-
* If the WALWriter is sleeping, we should kick it to make it come out of
2469-
* low-power mode. Otherwise, determine whether there's a full page of
2470-
* WAL available to write.
2471+
* If somebody else already called this function with a more aggressive
2472+
* LSN, they will have done what we needed (and perhaps more).
24712473
*/
2472-
if (!sleeping)
2474+
if (asyncXactLSN <= prevAsyncXactLSN)
2475+
return;
2476+
2477+
/*
2478+
* If the WALWriter is sleeping, kick it to make it come out of low-power
2479+
* mode, so that this async commit will reach disk within the expected
2480+
* amount of time. Otherwise, determine whether it has enough WAL
2481+
* available to flush, the same way that XLogBackgroundFlush() does.
2482+
*/
2483+
if (sleeping)
2484+
wakeup = true;
2485+
else
24732486
{
2474-
/* back off to last completed page boundary */
2475-
WriteRqstPtr -= WriteRqstPtr % XLOG_BLCKSZ;
2487+
int flushblocks;
24762488

2477-
/* if we have already flushed that far, we're done */
2478-
if (WriteRqstPtr <= LogwrtResult.Flush)
2479-
return;
2489+
flushblocks =
2490+
WriteRqstPtr / XLOG_BLCKSZ - LogwrtResult.Flush / XLOG_BLCKSZ;
2491+
2492+
if (WalWriterFlushAfter == 0 || flushblocks >= WalWriterFlushAfter)
2493+
wakeup = true;
24802494
}
24812495

2482-
/*
2483-
* Nudge the WALWriter: it has a full page of WAL to write, or we want it
2484-
* to come out of low-power mode so that this async commit will reach disk
2485-
* within the expected amount of time.
2486-
*/
2487-
if (ProcGlobal->walwriterLatch)
2496+
if (wakeup && ProcGlobal->walwriterLatch)
24882497
SetLatch(ProcGlobal->walwriterLatch);
24892498
}
24902499

@@ -2803,7 +2812,7 @@ XLogBackgroundFlush(void)
28032812
bool flexible = true;
28042813
static TimestampTz lastflush;
28052814
TimestampTz now;
2806-
int flushbytes;
2815+
int flushblocks;
28072816
TimeLineID insertTLI;
28082817

28092818
/* XLOG doesn't need flushing during recovery */
@@ -2855,9 +2864,13 @@ XLogBackgroundFlush(void)
28552864
/*
28562865
* Determine how far to flush WAL, based on the wal_writer_delay and
28572866
* wal_writer_flush_after GUCs.
2867+
*
2868+
* Note that XLogSetAsyncXactLSN() performs similar calculation based on
2869+
* wal_writer_flush_after, to decide when to wake us up. Make sure the
2870+
* logic is the same in both places if you change this.
28582871
*/
28592872
now = GetCurrentTimestamp();
2860-
flushbytes =
2873+
flushblocks =
28612874
WriteRqst.Write / XLOG_BLCKSZ - LogwrtResult.Flush / XLOG_BLCKSZ;
28622875

28632876
if (WalWriterFlushAfter == 0 || lastflush == 0)
@@ -2876,7 +2889,7 @@ XLogBackgroundFlush(void)
28762889
WriteRqst.Flush = WriteRqst.Write;
28772890
lastflush = now;
28782891
}
2879-
else if (flushbytes >= WalWriterFlushAfter)
2892+
else if (flushblocks >= WalWriterFlushAfter)
28802893
{
28812894
/* exceeded wal_writer_flush_after blocks, flush */
28822895
WriteRqst.Flush = WriteRqst.Write;

0 commit comments

Comments
 (0)