aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/buffer/bufmgr.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2012-01-26 18:19:48 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2012-01-26 18:39:13 +0200
commit6d90eaaa89a007e0d365f49d6436f35d2392cfeb (patch)
tree625c4dc75f0067c438696b9ebc96715521635e2f /src/backend/storage/buffer/bufmgr.c
parent467ff207f51439cadee7857d6a0874f34652ed53 (diff)
downloadpostgresql-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.c41
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);
}
}