On Mon, 2004-12-27 at 22:21, Bruce Momjian wrote: > Should we consider at least adjusting the meaning of bgwriter_percent?
Yes. As things stand, this is the only change that seems safe. Here's a very short patch that implements this change within BufferSync in bufmgr.c - No algorithm changes - No error message changes - Only change is the call to StrategyDirtyBufferList is made using the maximum number of buffers that will be cleaned, rather than uselessly trawling through all of shared_buffers This changes the meaning of bgwriter_percent from "percent of dirty buffers" to "percent of shared_buffers". The default settings of 1% of 1000 buffers gives up to 10 dirty block writes every 250ms Benefit: allows performance tuning by increases options for setting bgwriter_delay which would otherwise have an ineffectually high minimum setting Risk: low 1-line doc patch to follow, if this is approved. -- Best Regards, Simon Riggs
Index: src/backend/storage/buffer/bufmgr.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v retrieving revision 1.182 diff -d -c -r1.182 bufmgr.c *** src/backend/storage/buffer/bufmgr.c 24 Nov 2004 02:56:17 -0000 1.182 --- src/backend/storage/buffer/bufmgr.c 30 Dec 2004 23:52:24 -0000 *************** *** 681,686 **** --- 681,687 ---- { BufferDesc **dirty_buffers; BufferTag *buftags; + int dirty_buffers_maxlen = 1; int num_buffer_dirty; int i; *************** *** 688,717 **** if (percent == 0 || maxpages == 0) return 0; /* ! * Get a list of all currently dirty buffers and how many there are. * We do not flush buffers that get dirtied after we started. They ! * have to wait until the next checkpoint. */ ! dirty_buffers = (BufferDesc **) palloc(NBuffers * sizeof(BufferDesc *)); ! buftags = (BufferTag *) palloc(NBuffers * sizeof(BufferTag)); LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); - num_buffer_dirty = StrategyDirtyBufferList(dirty_buffers, buftags, - NBuffers); ! /* ! * If called by the background writer, we are usually asked to only ! * write out some portion of dirty buffers now, to prevent the IO ! * storm at checkpoint time. ! */ ! if (percent > 0) ! { ! Assert(percent <= 100); ! num_buffer_dirty = (num_buffer_dirty * percent + 99) / 100; ! } ! if (maxpages > 0 && num_buffer_dirty > maxpages) ! num_buffer_dirty = maxpages; /* Make sure we can handle the pin inside the loop */ ResourceOwnerEnlargeBuffers(CurrentResourceOwner); --- 689,719 ---- if (percent == 0 || maxpages == 0) return 0; + /* Set number of buffers we will clean at LRUs of buffer lists */ + if (percent > 0 ) { + Assert(percent <= 100); + dirty_buffers_maxlen = (NBuffers * percent + 99) / 100; + } + if (maxpages > 0 && dirty_buffers_maxlen > maxpages) + dirty_buffers_maxlen = maxpages; + + /* if checkpoint time */ + if (percent == -1 && maxpages == -1) + dirty_buffers_maxlen = NBuffers; + /* ! * Get a list of dirty buffers to clean and how many there are. * We do not flush buffers that get dirtied after we started. They ! * have to wait until the next call of this function */ ! dirty_buffers = ! (BufferDesc **) palloc(dirty_buffers_maxlen * sizeof(BufferDesc *)); ! buftags = (BufferTag *) palloc(dirty_buffers_maxlen * sizeof(BufferTag)); LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); ! num_buffer_dirty = StrategyDirtyBufferList(dirty_buffers, buftags, ! dirty_buffers_maxlen); /* Make sure we can handle the pin inside the loop */ ResourceOwnerEnlargeBuffers(CurrentResourceOwner);
---------------------------(end of broadcast)--------------------------- TIP 8: explain analyze is your friend