Index: src/backend/storage/buffer/freelist.c
===================================================================
*** src/backend/storage/buffer/freelist.c	(HEAD)
--- src/backend/storage/buffer/freelist.c	(working copy)
*************** typedef struct
*** 29,34 ****
--- 29,35 ----
  
  	int			firstFreeBuffer;	/* Head of list of unused buffers */
  	int			lastFreeBuffer; /* Tail of list of unused buffers */
+ 	int			numFreeBuffers;	/* Number of unused buffers */
  
  	/*
  	 * NOTE: lastFreeBuffer is undefined when firstFreeBuffer is -1 (that is,
*************** volatile BufferDesc *
*** 59,64 ****
--- 60,67 ----
  StrategyGetBuffer(void)
  {
  	volatile BufferDesc *buf;
+ 	volatile int		*freeBuffer;
+ 	int			lastBuffer;
  	int			trycounter;
  
  	LWLockAcquire(BufFreelistLock, LW_EXCLUSIVE);
*************** StrategyGetBuffer(void)
*** 69,82 ****
  	 * individual buffer spinlocks, so it's OK to manipulate them without
  	 * holding the spinlock.
  	 */
! 	while (StrategyControl->firstFreeBuffer >= 0)
  	{
! 		buf = &BufferDescriptors[StrategyControl->firstFreeBuffer];
  		Assert(buf->freeNext != FREENEXT_NOT_IN_LIST);
  
  		/* Unconditionally remove buffer from freelist */
! 		StrategyControl->firstFreeBuffer = buf->freeNext;
  		buf->freeNext = FREENEXT_NOT_IN_LIST;
  
  		/*
  		 * If the buffer is pinned or has a nonzero usage_count, we cannot use
--- 72,108 ----
  	 * individual buffer spinlocks, so it's OK to manipulate them without
  	 * holding the spinlock.
  	 */
! 	lastBuffer = FREENEXT_END_OF_LIST;
! 	freeBuffer = &StrategyControl->firstFreeBuffer;
! 	while (*freeBuffer >= 0)
  	{
! 		bool	unused;
! 
! 		buf = &BufferDescriptors[*freeBuffer];
  		Assert(buf->freeNext != FREENEXT_NOT_IN_LIST);
  
+ 		LockBufHdr(buf);
+ 		unused = (buf->refcount == 0 && buf->usage_count == 0);
+ 
+ 		/*
+ 		 * We don't reuse dirty buffers except there are more than
+ 		 * FREELIST_BUFFERS buffers in freelist to avoid WAL traffic.
+ 		 */
+ 		if ((buf->flags & BM_DIRTY) && unused &&
+ 			StrategyControl->numFreeBuffers < FREELIST_BUFFERS)
+ 		{
+ 			lastBuffer = *freeBuffer;
+ 			freeBuffer = &buf->freeNext;
+ 			UnlockBufHdr(buf);
+ 			continue;
+ 		}
+ 
  		/* Unconditionally remove buffer from freelist */
! 		*freeBuffer = buf->freeNext;
  		buf->freeNext = FREENEXT_NOT_IN_LIST;
+ 		StrategyControl->numFreeBuffers--;
+ 		if (*freeBuffer == FREENEXT_END_OF_LIST)
+ 			StrategyControl->lastFreeBuffer = lastBuffer;
  
  		/*
  		 * If the buffer is pinned or has a nonzero usage_count, we cannot use
*************** StrategyGetBuffer(void)
*** 84,91 ****
  		 * valid buffer in the freelist and then someone else used it before
  		 * we got to it.)
  		 */
! 		LockBufHdr(buf);
! 		if (buf->refcount == 0 && buf->usage_count == 0)
  			return buf;
  		UnlockBufHdr(buf);
  	}
--- 110,116 ----
  		 * valid buffer in the freelist and then someone else used it before
  		 * we got to it.)
  		 */
! 		if (unused)
  			return buf;
  		UnlockBufHdr(buf);
  	}
*************** StrategyGetBuffer(void)
*** 104,110 ****
  		 * it; decrement the usage_count and keep scanning.
  		 */
  		LockBufHdr(buf);
! 		if (buf->refcount == 0 && buf->usage_count == 0)
  			return buf;
  		if (buf->usage_count > 0)
  		{
--- 129,136 ----
  		 * it; decrement the usage_count and keep scanning.
  		 */
  		LockBufHdr(buf);
! 		if (buf->refcount == 0 && buf->usage_count == 0 &&
! 			buf->freeNext == FREENEXT_NOT_IN_LIST)
  			return buf;
  		if (buf->usage_count > 0)
  		{
*************** StrategyFreeBuffer(volatile BufferDesc *
*** 164,169 ****
--- 190,196 ----
  				BufferDescriptors[StrategyControl->lastFreeBuffer].freeNext = buf->buf_id;
  			StrategyControl->lastFreeBuffer = buf->buf_id;
  		}
+ 		StrategyControl->numFreeBuffers++;
  	}
  
  	LWLockRelease(BufFreelistLock);
*************** StrategyInitialize(bool init)
*** 267,272 ****
--- 294,300 ----
  		 */
  		StrategyControl->firstFreeBuffer = 0;
  		StrategyControl->lastFreeBuffer = NBuffers - 1;
+ 		StrategyControl->numFreeBuffers = NBuffers;
  
  		/* Initialize the clock sweep pointer */
  		StrategyControl->nextVictimBuffer = 0;
Index: src/include/storage/buf_internals.h
===================================================================
*** src/include/storage/buf_internals.h	(HEAD)
--- src/include/storage/buf_internals.h	(working copy)
*************** typedef struct sbufdesc
*** 149,154 ****
--- 149,160 ----
  #define FREENEXT_NOT_IN_LIST	(-2)
  
  /*
+  * Dirty buffers in freelist are not reused except there are more than the
+  * following number.
+  */
+ #define FREELIST_BUFFERS		32
+ 
+ /*
   * Macros for acquiring/releasing a shared buffer header's spinlock.
   * Do not apply these to local buffers!
   *