diff --git a/src/backend/storage/buffer/freelist.c b/src/backend/storage/buffer/freelist.c
index bf9903b..b2935af 100644
--- a/src/backend/storage/buffer/freelist.c
+++ b/src/backend/storage/buffer/freelist.c
@@ -108,6 +108,8 @@ StrategyGetBuffer(BufferAccessStrategy strategy, bool *lock_held)
 {
 	volatile BufferDesc *buf;
 	int			trycounter;
+	int			freelist_limit;	/* How fast we get less choosy if no victims */
+	int			usage_limit;	/* How choosy we are about our next victim */
 
 	/*
 	 * If given a strategy object, see whether it can select a buffer. We
@@ -167,7 +169,12 @@ StrategyGetBuffer(BufferAccessStrategy strategy, bool *lock_held)
 	}
 
 	/* Nothing on the freelist, so run the "clock sweep" algorithm */
-	trycounter = NBuffers;
+	trycounter = 0;
+
+#define FREELIST_WORST_CASE_LIMIT	16	
+	usage_limit = 0;
+	freelist_limit = FREELIST_WORST_CASE_LIMIT;
+
 	for (;;)
 	{
 		buf = &BufferDescriptors[StrategyControl->nextVictimBuffer];
@@ -179,16 +186,28 @@ StrategyGetBuffer(BufferAccessStrategy strategy, bool *lock_held)
 		}
 
 		/*
-		 * If the buffer is pinned or has a nonzero usage_count, we cannot use
-		 * it; decrement the usage_count (unless pinned) and keep scanning.
+		 * If the buffer is pinned we cannot use it.
+		 *
+		 * We first look for a buffer with usage_count == 0, but limiting out
+		 * search to the first FREELIST_WORST_CASE_LIMIT buffers. We slowly
+		 * get less choosy if the buffers we see are all popular.
+		 *
+		 * This is designed to give O(k) worst case behaviour in cases
+		 * where there are many popular buffers and shared buffers is large,
+		 * which is common since those two siituations are related.
 		 */
 		LockBufHdr(buf);
 		if (buf->refcount == 0)
 		{
-			if (buf->usage_count > 0)
+			if (buf->usage_count > usage_limit)
 			{
 				buf->usage_count--;
-				trycounter = NBuffers;
+				if (trycounter++ > freelist_limit)
+				{
+					trycounter = 0;
+					usage_limit++;
+					freelist_limit *= 2;
+				}
 			}
 			else
 			{
@@ -198,7 +217,7 @@ StrategyGetBuffer(BufferAccessStrategy strategy, bool *lock_held)
 				return buf;
 			}
 		}
-		else if (--trycounter == 0)
+		else if (trycounter++ >= NBuffers)
 		{
 			/*
 			 * We've scanned all the buffers without making any state changes,
