diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2012-01-26 18:19:48 +0200 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2012-01-26 18:39:13 +0200 |
commit | 6d90eaaa89a007e0d365f49d6436f35d2392cfeb (patch) | |
tree | 625c4dc75f0067c438696b9ebc96715521635e2f /src/backend/storage/buffer/bufmgr.c | |
parent | 467ff207f51439cadee7857d6a0874f34652ed53 (diff) | |
download | postgresql-6d90eaaa89a007e0d365f49d6436f35d2392cfeb.tar.gz postgresql-6d90eaaa89a007e0d365f49d6436f35d2392cfeb.zip |
Make bgwriter sleep longer when it has no work to do, to save electricity.
To make it wake up promptly when activity starts again, backends nudge it
by setting a latch in MarkBufferDirty(). The latch is kept set while
bgwriter is active, so there is very little overhead from that when the
system is busy. It is only armed before going into longer sleep.
Peter Geoghegan, with some changes by me.
Diffstat (limited to 'src/backend/storage/buffer/bufmgr.c')
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 8f68bcc66d9..1adb6d360dd 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -953,6 +953,7 @@ void MarkBufferDirty(Buffer buffer) { volatile BufferDesc *bufHdr; + bool dirtied = false; if (!BufferIsValid(buffer)) elog(ERROR, "bad buffer ID: %d", buffer); @@ -973,19 +974,25 @@ MarkBufferDirty(Buffer buffer) Assert(bufHdr->refcount > 0); + if (!(bufHdr->flags & BM_DIRTY)) + dirtied = true; + + bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED); + + UnlockBufHdr(bufHdr); + /* - * If the buffer was not dirty already, do vacuum accounting. + * If the buffer was not dirty already, do vacuum accounting, and + * nudge bgwriter. */ - if (!(bufHdr->flags & BM_DIRTY)) + if (dirtied) { VacuumPageDirty++; if (VacuumCostActive) VacuumCostBalance += VacuumCostPageDirty; + if (ProcGlobal->bgwriterLatch) + SetLatch(ProcGlobal->bgwriterLatch); } - - bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED); - - UnlockBufHdr(bufHdr); } /* @@ -1307,8 +1314,12 @@ BufferSync(int flags) * BgBufferSync -- Write out some dirty buffers in the pool. * * This is called periodically by the background writer process. + * + * Returns true if the clocksweep has been "lapped", so that there's nothing + * to do. Also returns true if there's nothing to do because bgwriter was + * effectively disabled by setting bgwriter_lru_maxpages to 0. */ -void +bool BgBufferSync(void) { /* info obtained from freelist.c */ @@ -1365,7 +1376,7 @@ BgBufferSync(void) if (bgwriter_lru_maxpages <= 0) { saved_info_valid = false; - return; + return true; } /* @@ -1584,6 +1595,8 @@ BgBufferSync(void) recent_alloc, strategy_delta, scans_per_alloc, smoothed_density); #endif } + + return (bufs_to_lap == 0); } /* @@ -2341,16 +2354,24 @@ SetBufferCommitInfoNeedsSave(Buffer buffer) if ((bufHdr->flags & (BM_DIRTY | BM_JUST_DIRTIED)) != (BM_DIRTY | BM_JUST_DIRTIED)) { + bool dirtied = false; + LockBufHdr(bufHdr); Assert(bufHdr->refcount > 0); if (!(bufHdr->flags & BM_DIRTY)) + dirtied = true; + bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED); + UnlockBufHdr(bufHdr); + + if (dirtied) { VacuumPageDirty++; if (VacuumCostActive) VacuumCostBalance += VacuumCostPageDirty; + /* The bgwriter may need to be woken. */ + if (ProcGlobal->bgwriterLatch) + SetLatch(ProcGlobal->bgwriterLatch); } - bufHdr->flags |= (BM_DIRTY | BM_JUST_DIRTIED); - UnlockBufHdr(bufHdr); } } |