diff -cpr HEAD/doc/src/sgml/config.sgml pgsql-bgwriter/doc/src/sgml/config.sgml
*** HEAD/doc/src/sgml/config.sgml Mon Mar 5 09:48:58 2007
--- pgsql-bgwriter/doc/src/sgml/config.sgml Mon Mar 5 12:39:42 2007
*************** SET ENABLE_SEQSCAN TO OFF;
*** 1208,1248 ****
-
- bgwriter_lru_percent (floating point)
-
- bgwriter_lru_percent> configuration parameter
-
-
-
- To reduce the probability that server processes will need to issue
- their own writes, the background writer tries to write buffers that
- are likely to be recycled soon. In each round, it examines up to
- bgwriter_lru_percent> of the buffers that are nearest to
- being recycled, and writes any that are dirty.
- The default value is 1.0 (1% of the total number of shared buffers).
- This parameter can only be set in the postgresql.conf>
- file or on the server command line.
-
-
-
-
-
- bgwriter_lru_maxpages (integer)
-
- bgwriter_lru_maxpages> configuration parameter
-
-
-
- In each round, no more than this many buffers will be written
- as a result of scanning soon-to-be-recycled buffers.
- The default value is five buffers.
- This parameter can only be set in the postgresql.conf>
- file or on the server command line.
-
-
-
-
bgwriter_all_percent (floating point)
--- 1208,1213 ----
*************** SET ENABLE_SEQSCAN TO OFF;
*** 1290,1303 ****
caused by the background writer, but leave more work to be done
at checkpoint time. To reduce load spikes at checkpoints,
increase these two values.
- Similarly, smaller values of bgwriter_lru_percent and
- bgwriter_lru_maxpages reduce the extra I/O load
- caused by the background writer, but make it more likely that server
- processes will have to issue writes for themselves, delaying interactive
- queries.
To disable background writing entirely,
! set both maxpages values and/or both
! percent values to zero.
--- 1255,1269 ----
caused by the background writer, but leave more work to be done
at checkpoint time. To reduce load spikes at checkpoints,
increase these two values.
To disable background writing entirely,
! set bgwriter_all_percent value and/or
! bgwriter_all_maxpages value to zero.
!
!
! Also, to reduce the probability that server processes will need to
! issue their own writes, the background writer tries to write buffers
! that are likely to be recycled soon. The amount of writes are adjusted
! automatically.
diff -cpr HEAD/src/backend/postmaster/bgwriter.c pgsql-bgwriter/src/backend/postmaster/bgwriter.c
*** HEAD/src/backend/postmaster/bgwriter.c Mon Jan 22 13:08:10 2007
--- pgsql-bgwriter/src/backend/postmaster/bgwriter.c Mon Mar 5 12:40:14 2007
*************** static volatile sig_atomic_t shutdown_re
*** 141,147 ****
/*
* Private state
*/
! static bool am_bg_writer = false;
static bool ckpt_active = false;
--- 141,147 ----
/*
* Private state
*/
! /*static*/ bool am_bg_writer = false; /* ONLY FOR DEBUG */
static bool ckpt_active = false;
*************** BackgroundWriterMain(void)
*** 484,491 ****
*
* We absorb pending requests after each short sleep.
*/
! if ((bgwriter_all_percent > 0.0 && bgwriter_all_maxpages > 0) ||
! (bgwriter_lru_percent > 0.0 && bgwriter_lru_maxpages > 0))
udelay = BgWriterDelay * 1000L;
else if (XLogArchiveTimeout > 0)
udelay = 1000000L; /* One second */
--- 484,490 ----
*
* We absorb pending requests after each short sleep.
*/
! if (bgwriter_all_percent > 0.0 && bgwriter_all_maxpages > 0)
udelay = BgWriterDelay * 1000L;
else if (XLogArchiveTimeout > 0)
udelay = 1000000L; /* One second */
diff -cpr HEAD/src/backend/storage/buffer/bufmgr.c pgsql-bgwriter/src/backend/storage/buffer/bufmgr.c
*** HEAD/src/backend/storage/buffer/bufmgr.c Mon Feb 5 10:35:58 2007
--- pgsql-bgwriter/src/backend/storage/buffer/bufmgr.c Mon Mar 5 12:41:09 2007
***************
*** 62,72 ****
/* GUC variables */
bool zero_damaged_pages = false;
- double bgwriter_lru_percent = 1.0;
double bgwriter_all_percent = 0.333;
- int bgwriter_lru_maxpages = 5;
int bgwriter_all_maxpages = 5;
long NDirectFileRead; /* some I/O's are direct file access. bypass
* bufmgr */
--- 62,71 ----
/* GUC variables */
bool zero_damaged_pages = false;
double bgwriter_all_percent = 0.333;
int bgwriter_all_maxpages = 5;
+ static int bgwriter_lru_maxpages = 5; /* adjusted automatically */
long NDirectFileRead; /* some I/O's are direct file access. bypass
* bufmgr */
*************** BufferSync(void)
*** 945,956 ****
{
int buf_id;
int num_to_scan;
int absorb_counter;
/*
* Find out where to start the circular scan.
*/
! buf_id = StrategySyncStart();
/* Make sure we can handle the pin inside SyncOneBuffer */
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
--- 944,956 ----
{
int buf_id;
int num_to_scan;
+ int num_to_clean;
int absorb_counter;
/*
* Find out where to start the circular scan.
*/
! buf_id = StrategySyncStart(&num_to_clean);
/* Make sure we can handle the pin inside SyncOneBuffer */
ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
*************** BgBufferSync(void)
*** 992,997 ****
--- 992,998 ----
static int buf_id1 = 0;
int buf_id2;
int num_to_scan;
+ int num_to_clean;
int num_written;
/* Make sure we can handle the pin inside SyncOneBuffer */
*************** BgBufferSync(void)
*** 1036,1058 ****
* This loop considers only unpinned buffers close to the clock sweep
* point.
*/
! if (bgwriter_lru_percent > 0.0 && bgwriter_lru_maxpages > 0)
! {
! num_to_scan = (int) ((NBuffers * bgwriter_lru_percent + 99) / 100);
! num_written = 0;
! buf_id2 = StrategySyncStart();
! while (num_to_scan-- > 0)
! {
! if (SyncOneBuffer(buf_id2, true))
! {
! if (++num_written >= bgwriter_lru_maxpages)
! break;
! }
! if (++buf_id2 >= NBuffers)
! buf_id2 = 0;
! }
}
}
--- 1037,1061 ----
* This loop considers only unpinned buffers close to the clock sweep
* point.
*/
! buf_id2 = StrategySyncStart(&num_to_clean);
! if (bgwriter_lru_maxpages < num_to_clean)
! bgwriter_lru_maxpages -= 1;
! else
! bgwriter_lru_maxpages += 1;
! {
! static int counter = 0;
! if ((++counter) % 50 == 0)
! elog(LOG, "bgwriter_lru_maxpages = %d", bgwriter_lru_maxpages);
! }
! num_written = 0;
! while (num_written < bgwriter_lru_maxpages)
! {
! if (SyncOneBuffer(buf_id2, true))
! ++num_written;
! if (++buf_id2 >= NBuffers)
! buf_id2 = 0;
}
}
*************** BgBufferSync(void)
*** 1062,1070 ****
* If skip_pinned is true, we don't write currently-pinned buffers, nor
* buffers marked recently used, as these are not replacement candidates.
*
! * Returns true if buffer was written, else false. (This could be in error
! * if FlushBuffers finds the buffer clean after locking it, but we don't
! * care all that much.)
*
* Note: caller must have done ResourceOwnerEnlargeBuffers.
*/
--- 1065,1073 ----
* If skip_pinned is true, we don't write currently-pinned buffers, nor
* buffers marked recently used, as these are not replacement candidates.
*
! * Returns true if buffer was written or recyclable soon, else false.
! * (This could be in error if FlushBuffers finds the buffer clean after
! * locking it, but we don't care all that much.)
*
* Note: caller must have done ResourceOwnerEnlargeBuffers.
*/
*************** SyncOneBuffer(int buf_id, bool skip_pinn
*** 1083,1098 ****
* upcoming changes and so we are not required to write such dirty buffer.
*/
LockBufHdr(bufHdr);
! if (!(bufHdr->flags & BM_VALID) || !(bufHdr->flags & BM_DIRTY))
{
UnlockBufHdr(bufHdr);
return false;
}
! if (skip_pinned &&
! (bufHdr->refcount != 0 || bufHdr->usage_count != 0))
{
UnlockBufHdr(bufHdr);
! return false;
}
/*
--- 1086,1101 ----
* upcoming changes and so we are not required to write such dirty buffer.
*/
LockBufHdr(bufHdr);
! if (skip_pinned &&
! (bufHdr->refcount != 0 || bufHdr->usage_count != 0))
{
UnlockBufHdr(bufHdr);
return false;
}
! if (!(bufHdr->flags & BM_VALID) || !(bufHdr->flags & BM_DIRTY))
{
UnlockBufHdr(bufHdr);
! return skip_pinned; /* We can recycle non dirty buffers soon. */
}
/*
*************** PrintBufferLeakWarning(Buffer buffer)
*** 1272,1279 ****
--- 1275,1284 ----
void
FlushBufferPool(void)
{
+ StrategyShowReports(); /* ONLY FOR DEBUG */
BufferSync();
smgrsync();
+ StrategyShowReports(); /* ONLY FOR DEBUG */
}
*************** FlushBuffer(volatile BufferDesc *buf, SM
*** 1365,1370 ****
--- 1370,1377 ----
if (!StartBufferIO(buf, false))
return;
+ StrategyReportWrite(); /* ONLY FOR DEBUG */
+
/* Setup error traceback support for ereport() */
errcontext.callback = buffer_write_error_callback;
errcontext.arg = (void *) buf;
diff -cpr HEAD/src/backend/storage/buffer/freelist.c pgsql-bgwriter/src/backend/storage/buffer/freelist.c
*** HEAD/src/backend/storage/buffer/freelist.c Thu Jan 11 14:20:57 2007
--- pgsql-bgwriter/src/backend/storage/buffer/freelist.c Mon Mar 5 12:36:35 2007
*************** typedef struct
*** 27,32 ****
--- 27,37 ----
/* Clock sweep hand: index of next buffer to consider grabbing */
int nextVictimBuffer;
+ int numGetBuffer; /* Buffer request count per cycle */
+
+ int writtenByBgWriter; /* ONLY FOR DEBUG */
+ int writtenByBackends; /* ONLY FOR DEBUG */
+
int firstFreeBuffer; /* Head of list of unused buffers */
int lastFreeBuffer; /* Tail of list of unused buffers */
*************** StrategyGetBuffer(void)
*** 63,68 ****
--- 68,75 ----
LWLockAcquire(BufFreelistLock, LW_EXCLUSIVE);
+ StrategyControl->numGetBuffer++;
+
/*
* Try to get a buffer from the freelist. Note that the freeNext fields
* are considered to be protected by the BufFreelistLock not the
*************** StrategyFreeBuffer(volatile BufferDesc *
*** 176,191 ****
* BufferSync() will proceed circularly around the buffer array from there.
*/
int
! StrategySyncStart(void)
{
int result;
- /*
- * We could probably dispense with the locking here, but just to be safe
- * ...
- */
LWLockAcquire(BufFreelistLock, LW_EXCLUSIVE);
result = StrategyControl->nextVictimBuffer;
LWLockRelease(BufFreelistLock);
return result;
}
--- 183,196 ----
* BufferSync() will proceed circularly around the buffer array from there.
*/
int
! StrategySyncStart(int *num_to_clean)
{
int result;
LWLockAcquire(BufFreelistLock, LW_EXCLUSIVE);
result = StrategyControl->nextVictimBuffer;
+ *num_to_clean = StrategyControl->numGetBuffer * 2; /* safety margin */
+ StrategyControl->numGetBuffer = 0;
LWLockRelease(BufFreelistLock);
return result;
}
*************** StrategyInitialize(bool init)
*** 270,276 ****
--- 275,303 ----
/* Initialize the clock sweep pointer */
StrategyControl->nextVictimBuffer = 0;
+
+ StrategyControl->numGetBuffer = 0;
+ StrategyControl->writtenByBgWriter = 0;
+ StrategyControl->writtenByBackends = 0;
}
else
Assert(!init);
}
+
+ void
+ StrategyReportWrite(void)
+ {
+ extern bool am_bg_writer;
+ if (am_bg_writer)
+ StrategyControl->writtenByBgWriter++;
+ else
+ StrategyControl->writtenByBackends++;
+ }
+
+ void
+ StrategyShowReports(void)
+ {
+ elog(LOG, "Write stats : bgwriter/backends = %d/%d",
+ StrategyControl->writtenByBgWriter,
+ StrategyControl->writtenByBackends);
+ }
diff -cpr HEAD/src/backend/utils/misc/guc.c pgsql-bgwriter/src/backend/utils/misc/guc.c
*** HEAD/src/backend/utils/misc/guc.c Mon Mar 5 09:48:58 2007
--- pgsql-bgwriter/src/backend/utils/misc/guc.c Mon Mar 5 12:39:42 2007
*************** static struct config_int ConfigureNamesI
*** 1505,1519 ****
},
{
- {"bgwriter_lru_maxpages", PGC_SIGHUP, RESOURCES,
- gettext_noop("Background writer maximum number of LRU pages to flush per round."),
- NULL
- },
- &bgwriter_lru_maxpages,
- 5, 0, 1000, NULL, NULL
- },
-
- {
{"bgwriter_all_maxpages", PGC_SIGHUP, RESOURCES,
gettext_noop("Background writer maximum number of all pages to flush per round."),
NULL
--- 1505,1510 ----
*************** static struct config_real ConfigureNames
*** 1757,1771 ****
},
{
- {"bgwriter_lru_percent", PGC_SIGHUP, RESOURCES,
- gettext_noop("Background writer percentage of LRU buffers to flush per round."),
- NULL
- },
- &bgwriter_lru_percent,
- 1.0, 0.0, 100.0, NULL, NULL
- },
-
- {
{"bgwriter_all_percent", PGC_SIGHUP, RESOURCES,
gettext_noop("Background writer percentage of all buffers to flush per round."),
NULL
--- 1748,1753 ----
diff -cpr HEAD/src/backend/utils/misc/postgresql.conf.sample pgsql-bgwriter/src/backend/utils/misc/postgresql.conf.sample
*** HEAD/src/backend/utils/misc/postgresql.conf.sample Mon Mar 5 09:48:58 2007
--- pgsql-bgwriter/src/backend/utils/misc/postgresql.conf.sample Mon Mar 5 12:39:42 2007
***************
*** 138,146 ****
# - Background writer -
#bgwriter_delay = 200ms # 10-10000ms between rounds
! #bgwriter_lru_percent = 1.0 # 0-100% of LRU buffers scanned/round
! #bgwriter_lru_maxpages = 5 # 0-1000 buffers max written/round
! #bgwriter_all_percent = 0.333 # 0-100% of all buffers scanned/round
#bgwriter_all_maxpages = 5 # 0-1000 buffers max written/round
--- 138,144 ----
# - Background writer -
#bgwriter_delay = 200ms # 10-10000ms between rounds
! #bgwriter_all_percent = 0.333 # 0-100% of buffers scanned/round
#bgwriter_all_maxpages = 5 # 0-1000 buffers max written/round
diff -cpr HEAD/src/include/storage/buf_internals.h pgsql-bgwriter/src/include/storage/buf_internals.h
*** HEAD/src/include/storage/buf_internals.h Thu Jan 11 14:20:57 2007
--- pgsql-bgwriter/src/include/storage/buf_internals.h Mon Mar 5 12:36:35 2007
*************** extern long int LocalBufferFlushCount;
*** 186,195 ****
/* freelist.c */
extern volatile BufferDesc *StrategyGetBuffer(void);
extern void StrategyFreeBuffer(volatile BufferDesc *buf, bool at_head);
! extern int StrategySyncStart(void);
extern Size StrategyShmemSize(void);
extern void StrategyInitialize(bool init);
/* buf_table.c */
extern Size BufTableShmemSize(int size);
extern void InitBufTable(int size);
--- 186,198 ----
/* freelist.c */
extern volatile BufferDesc *StrategyGetBuffer(void);
extern void StrategyFreeBuffer(volatile BufferDesc *buf, bool at_head);
! extern int StrategySyncStart(int *num_to_clean);
extern Size StrategyShmemSize(void);
extern void StrategyInitialize(bool init);
+ extern void StrategyReportWrite(void); /* ONLY FOR DEBUG */
+ extern void StrategyShowReports(void); /* ONLY FOR DEBUG */
+
/* buf_table.c */
extern Size BufTableShmemSize(int size);
extern void InitBufTable(int size);
diff -cpr HEAD/src/include/storage/bufmgr.h pgsql-bgwriter/src/include/storage/bufmgr.h
*** HEAD/src/include/storage/bufmgr.h Thu Jan 11 14:20:57 2007
--- pgsql-bgwriter/src/include/storage/bufmgr.h Mon Mar 5 12:39:42 2007
*************** extern DLLIMPORT int NBuffers;
*** 24,32 ****
/* in bufmgr.c */
extern bool zero_damaged_pages;
- extern double bgwriter_lru_percent;
extern double bgwriter_all_percent;
- extern int bgwriter_lru_maxpages;
extern int bgwriter_all_maxpages;
/* in buf_init.c */
--- 24,30 ----