Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5461564

Browse files
committed
Reduce idle power consumption of walwriter and checkpointer processes.
This patch modifies the walwriter process so that, when it has not foundanything useful to do for many consecutive wakeup cycles, it extends itssleep time to reduce the server's idle power consumption. It reverts tonormal as soon as it's done any successful flushes. It's still true thatduring any async commit, backends check for completed, unflushed pages ofWAL and signal the walwriter if there are any; so that in practice thewalwriter can get awakened and returned to normal operation sooner than thesleep time might suggest.Also, improve the checkpointer so that it uses a latch and a computed delaytime to not wake up at all except when it has something to do, replacing aprevious hardcoded 0.5 sec wakeup cycle. This also is primarily useful forreducing the server's power consumption when idle.In passing, get rid of the dedicated latch for signaling the walwriter infavor of using its procLatch, since that comports better with possiblegeneric signal handlers using that latch. Also, fix a pre-existing bugwith failure to save/restore errno in walwriter's signal handlers.Peter Geoghegan, somewhat simplified by Tom
1 parent081ca7a commit5461564

File tree

7 files changed

+189
-59
lines changed

7 files changed

+189
-59
lines changed

‎src/backend/access/transam/xlog.c

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -433,11 +433,6 @@ typedef struct XLogCtlData
433433
*/
434434
LatchrecoveryWakeupLatch;
435435

436-
/*
437-
* WALWriterLatch is used to wake up the WALWriter to write some WAL.
438-
*/
439-
LatchWALWriterLatch;
440-
441436
/*
442437
* During recovery, we keep a copy of the latest checkpoint record here.
443438
* Used by the background writer when it wants to create a restartpoint.
@@ -1935,7 +1930,8 @@ XLogSetAsyncXactLSN(XLogRecPtr asyncXactLSN)
19351930
/*
19361931
* Nudge the WALWriter if we have a full page of WAL to write.
19371932
*/
1938-
SetLatch(&XLogCtl->WALWriterLatch);
1933+
if (ProcGlobal->walwriterLatch)
1934+
SetLatch(ProcGlobal->walwriterLatch);
19391935
}
19401936

19411937
/*
@@ -2167,22 +2163,25 @@ XLogFlush(XLogRecPtr record)
21672163
* block, and flush through the latest one of those. Thus, if async commits
21682164
* are not being used, we will flush complete blocks only.We can guarantee
21692165
* that async commits reach disk after at most three cycles; normally only
2170-
* one or two.(We allow XLogWrite to write "flexibly", meaning it can stop
2171-
* at the end of the buffer ring; this makes a difference only with very high
2172-
* load or long wal_writer_delay, but imposes one extra cycle for the worst
2173-
* case for async commits.)
2166+
* one or two. (When flushing complete blocks, we allow XLogWrite to write
2167+
*"flexibly", meaning it can stopat the end of the buffer ring; this makes a
2168+
*difference only with very highload or long wal_writer_delay, but imposes
2169+
*one extra cycle for the worstcase for async commits.)
21742170
*
21752171
* This routine is invoked periodically by the background walwriter process.
2172+
*
2173+
* Returns TRUE if we flushed anything.
21762174
*/
2177-
void
2175+
bool
21782176
XLogBackgroundFlush(void)
21792177
{
21802178
XLogRecPtrWriteRqstPtr;
21812179
boolflexible= true;
2180+
boolwrote_something= false;
21822181

21832182
/* XLOG doesn't need flushing during recovery */
21842183
if (RecoveryInProgress())
2185-
return;
2184+
return false;
21862185

21872186
/* read LogwrtResult and update local state */
21882187
{
@@ -2224,7 +2223,7 @@ XLogBackgroundFlush(void)
22242223
XLogFileClose();
22252224
}
22262225
}
2227-
return;
2226+
return false;
22282227
}
22292228

22302229
#ifdefWAL_DEBUG
@@ -2247,10 +2246,13 @@ XLogBackgroundFlush(void)
22472246
WriteRqst.Write=WriteRqstPtr;
22482247
WriteRqst.Flush=WriteRqstPtr;
22492248
XLogWrite(WriteRqst,flexible, false);
2249+
wrote_something= true;
22502250
}
22512251
LWLockRelease(WALWriteLock);
22522252

22532253
END_CRIT_SECTION();
2254+
2255+
returnwrote_something;
22542256
}
22552257

22562258
/*
@@ -5101,7 +5103,6 @@ XLOGShmemInit(void)
51015103
XLogCtl->Insert.currpage= (XLogPageHeader) (XLogCtl->pages);
51025104
SpinLockInit(&XLogCtl->info_lck);
51035105
InitSharedLatch(&XLogCtl->recoveryWakeupLatch);
5104-
InitSharedLatch(&XLogCtl->WALWriterLatch);
51055106

51065107
/*
51075108
* If we are not in bootstrap mode, pg_control should already exist. Read
@@ -10478,12 +10479,3 @@ WakeupRecovery(void)
1047810479
{
1047910480
SetLatch(&XLogCtl->recoveryWakeupLatch);
1048010481
}
10481-
10482-
/*
10483-
* Manage the WALWriterLatch
10484-
*/
10485-
Latch*
10486-
WALWriterLatch(void)
10487-
{
10488-
return&XLogCtl->WALWriterLatch;
10489-
}

‎src/backend/postmaster/checkpointer.c

Lines changed: 88 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include"storage/ipc.h"
5252
#include"storage/lwlock.h"
5353
#include"storage/pmsignal.h"
54+
#include"storage/proc.h"
5455
#include"storage/shmem.h"
5556
#include"storage/smgr.h"
5657
#include"storage/spin.h"
@@ -178,6 +179,7 @@ static void UpdateSharedMemoryConfig(void);
178179
staticvoidchkpt_quickdie(SIGNAL_ARGS);
179180
staticvoidChkptSigHupHandler(SIGNAL_ARGS);
180181
staticvoidReqCheckpointHandler(SIGNAL_ARGS);
182+
staticvoidchkpt_sigusr1_handler(SIGNAL_ARGS);
181183
staticvoidReqShutdownHandler(SIGNAL_ARGS);
182184

183185

@@ -224,7 +226,7 @@ CheckpointerMain(void)
224226
pqsignal(SIGQUIT,chkpt_quickdie);/* hard crash time */
225227
pqsignal(SIGALRM,SIG_IGN);
226228
pqsignal(SIGPIPE,SIG_IGN);
227-
pqsignal(SIGUSR1,SIG_IGN);/* reserve for ProcSignal */
229+
pqsignal(SIGUSR1,chkpt_sigusr1_handler);
228230
pqsignal(SIGUSR2,ReqShutdownHandler);/* request shutdown */
229231

230232
/*
@@ -359,6 +361,12 @@ CheckpointerMain(void)
359361
*/
360362
UpdateSharedMemoryConfig();
361363

364+
/*
365+
* Advertise our latch that backends can use to wake us up while we're
366+
* sleeping.
367+
*/
368+
ProcGlobal->checkpointerLatch=&MyProc->procLatch;
369+
362370
/*
363371
* Loop forever
364372
*/
@@ -368,6 +376,10 @@ CheckpointerMain(void)
368376
intflags=0;
369377
pg_time_tnow;
370378
intelapsed_secs;
379+
intcur_timeout;
380+
381+
/* Clear any already-pending wakeups */
382+
ResetLatch(&MyProc->procLatch);
371383

372384
/*
373385
* Emergency bailout if postmaster has died. This is to avoid the
@@ -387,15 +399,15 @@ CheckpointerMain(void)
387399
ProcessConfigFile(PGC_SIGHUP);
388400

389401
/*
390-
* Checkpointer is the last process toshutdown, so we ask
402+
* Checkpointer is the last process toshut down, so we ask
391403
* it to hold the keys for a range of other tasks required
392404
* most of which have nothing to do with checkpointing at all.
393405
*
394-
* For various reasons, some config values can change
395-
*dynamicallysoarethe primary copy of them is held in
396-
*shared memory to makesure all backends see the same value.
397-
*We make Checkpointerresponsible for updating the shared
398-
*memory copy if theparameter setting changes because of SIGHUP.
406+
* For various reasons, some config values can change dynamically
407+
* so the primary copy of them is held in shared memory to make
408+
* sure all backends see the same value. We make Checkpointer
409+
* responsible for updating the shared memory copy if the
410+
* parameter setting changes because of SIGHUP.
399411
*/
400412
UpdateSharedMemoryConfig();
401413
}
@@ -488,7 +500,7 @@ CheckpointerMain(void)
488500
errhint("Consider increasing the configuration parameter \"checkpoint_segments\".")));
489501

490502
/*
491-
* Initialize checkpointer-private variables used during checkpoint.
503+
* Initialize checkpointer-private variables used during checkpoint
492504
*/
493505
ckpt_active= true;
494506
if (!do_restartpoint)
@@ -543,20 +555,34 @@ CheckpointerMain(void)
543555
ckpt_active= false;
544556
}
545557

558+
/* Check for archive_timeout and switch xlog files if necessary. */
559+
CheckArchiveTimeout();
560+
546561
/*
547562
* Send off activity statistics to the stats collector
548563
*/
549564
pgstat_send_bgwriter();
550565

551566
/*
552-
* Nap for a while and then loop again. Later patches will replace
553-
* this with a latch loop. Keep it simple now for clarity.
554-
* Relatively long sleep because the bgwriter does cleanup now.
567+
* Sleep until we are signaled or it's time for another checkpoint
568+
* or xlog file switch.
555569
*/
556-
pg_usleep(500000L);
570+
now= (pg_time_t)time(NULL);
571+
elapsed_secs=now-last_checkpoint_time;
572+
if (elapsed_secs >=CheckPointTimeout)
573+
continue;/* no sleep for us ... */
574+
cur_timeout=CheckPointTimeout-elapsed_secs;
575+
if (XLogArchiveTimeout>0&& !RecoveryInProgress())
576+
{
577+
elapsed_secs=now-last_xlog_switch_time;
578+
if (elapsed_secs >=XLogArchiveTimeout)
579+
continue;/* no sleep for us ... */
580+
cur_timeout=Min(cur_timeout,XLogArchiveTimeout-elapsed_secs);
581+
}
557582

558-
/* Check for archive_timeout and switch xlog files if necessary. */
559-
CheckArchiveTimeout();
583+
(void)WaitLatch(&MyProc->procLatch,
584+
WL_LATCH_SET |WL_TIMEOUT |WL_POSTMASTER_DEATH,
585+
cur_timeout*1000L/* convert to ms */);
560586
}
561587
}
562588

@@ -814,21 +840,50 @@ chkpt_quickdie(SIGNAL_ARGS)
814840
staticvoid
815841
ChkptSigHupHandler(SIGNAL_ARGS)
816842
{
843+
intsave_errno=errno;
844+
817845
got_SIGHUP= true;
846+
if (MyProc)
847+
SetLatch(&MyProc->procLatch);
848+
849+
errno=save_errno;
818850
}
819851

820852
/* SIGINT: set flag to run a normal checkpoint right away */
821853
staticvoid
822854
ReqCheckpointHandler(SIGNAL_ARGS)
823855
{
856+
intsave_errno=errno;
857+
824858
checkpoint_requested= true;
859+
if (MyProc)
860+
SetLatch(&MyProc->procLatch);
861+
862+
errno=save_errno;
863+
}
864+
865+
/* SIGUSR1: used for latch wakeups */
866+
staticvoid
867+
chkpt_sigusr1_handler(SIGNAL_ARGS)
868+
{
869+
intsave_errno=errno;
870+
871+
latch_sigusr1_handler();
872+
873+
errno=save_errno;
825874
}
826875

827876
/* SIGUSR2: set flag to run a shutdown checkpoint and exit */
828877
staticvoid
829878
ReqShutdownHandler(SIGNAL_ARGS)
830879
{
880+
intsave_errno=errno;
881+
831882
shutdown_requested= true;
883+
if (MyProc)
884+
SetLatch(&MyProc->procLatch);
885+
886+
errno=save_errno;
832887
}
833888

834889

@@ -1055,6 +1110,7 @@ ForwardFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
10551110
BlockNumbersegno)
10561111
{
10571112
BgWriterRequest*request;
1113+
booltoo_full;
10581114

10591115
if (!IsUnderPostmaster)
10601116
return false;/* probably shouldn't even get here */
@@ -1068,14 +1124,13 @@ ForwardFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
10681124
BgWriterShmem->num_backend_writes++;
10691125

10701126
/*
1071-
* If thebackground writer isn't running or the request queue is full,
1127+
* If thecheckpointer isn't running or the request queue is full,
10721128
* the backend will have to perform its own fsync request.But before
1073-
* forcing that to happen, we can try to compact the background writer
1074-
* request queue.
1129+
* forcing that to happen, we can try to compact the request queue.
10751130
*/
10761131
if (BgWriterShmem->checkpointer_pid==0||
1077-
(BgWriterShmem->num_requests >=BgWriterShmem->max_requests
1078-
&&!CompactCheckpointerRequestQueue()))
1132+
(BgWriterShmem->num_requests >=BgWriterShmem->max_requests&&
1133+
!CompactCheckpointerRequestQueue()))
10791134
{
10801135
/*
10811136
* Count the subset of writes where backends have to do their own
@@ -1085,11 +1140,23 @@ ForwardFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
10851140
LWLockRelease(BgWriterCommLock);
10861141
return false;
10871142
}
1143+
1144+
/* OK, insert request */
10881145
request=&BgWriterShmem->requests[BgWriterShmem->num_requests++];
10891146
request->rnode=rnode;
10901147
request->forknum=forknum;
10911148
request->segno=segno;
1149+
1150+
/* If queue is more than half full, nudge the checkpointer to empty it */
1151+
too_full= (BgWriterShmem->num_requests >=
1152+
BgWriterShmem->max_requests /2);
1153+
10921154
LWLockRelease(BgWriterCommLock);
1155+
1156+
/* ... but not till after we release the lock */
1157+
if (too_full&&ProcGlobal->checkpointerLatch)
1158+
SetLatch(ProcGlobal->checkpointerLatch);
1159+
10931160
return true;
10941161
}
10951162

@@ -1109,7 +1176,7 @@ ForwardFsyncRequest(RelFileNodeBackend rnode, ForkNumber forknum,
11091176
* practice: there's one queue entry per shared buffer.
11101177
*/
11111178
staticbool
1112-
CompactCheckpointerRequestQueue()
1179+
CompactCheckpointerRequestQueue(void)
11131180
{
11141181
structBgWriterSlotMapping
11151182
{
@@ -1230,7 +1297,7 @@ AbsorbFsyncRequests(void)
12301297
*/
12311298
LWLockAcquire(BgWriterCommLock,LW_EXCLUSIVE);
12321299

1233-
/* Transferwrite count into pending pgstats message */
1300+
/* Transferstats counts into pending pgstats message */
12341301
BgWriterStats.m_buf_written_backend+=BgWriterShmem->num_backend_writes;
12351302
BgWriterStats.m_buf_fsync_backend+=BgWriterShmem->num_backend_fsync;
12361303

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp