bgwritter_or_checkpoint_proc_moving_buf_to_freelist.2.patch

text/plain

Filename: bgwritter_or_checkpoint_proc_moving_buf_to_freelist.2.patch
Type: text/plain
Part: 0
Message: Re: [WIP PATCH] for Performance Improvement in Buffer Management

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
File+
src/backend/storage/buffer/bufmgr.c 113 1
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index dba19eb..87446cb 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -955,6 +955,88 @@ retry:
 	StrategyFreeBuffer(buf);
 }
 
+
+/*
+ * MoveBufferToFreeList -- mark a shared buffer invalid and return it to the
+ * freelist. which is similar to InvalidateBuffer function.
+ */
+static void
+MoveBufferToFreeList(volatile BufferDesc *buf)
+{
+	BufferTag	oldTag;
+	uint32		oldHash;				/* hash value for oldTag */
+	LWLockId	oldPartitionLock;		/* buffer partition lock for it */
+	BufFlags	oldFlags;
+
+	/* Save the original buffer tag before dropping the spinlock */
+	oldTag = buf->tag;
+
+	UnlockBufHdr(buf);
+
+	/*
+	 * Need to compute the old tag's hashcode and partition lock ID. XXX is it
+	 * worth storing the hashcode in BufferDesc so we need not recompute it
+	 * here?  Probably not.
+	 */
+	oldHash = BufTableHashCode(&oldTag);
+	oldPartitionLock = BufMappingPartitionLock(oldHash);
+
+
+	/*
+	 * Acquire exclusive mapping lock in preparation for changing the buffer's
+	 * association.
+	 */
+	LWLockAcquire(oldPartitionLock, LW_EXCLUSIVE);
+
+	/* Re-lock the buffer header */
+	LockBufHdr(buf);
+
+	/* If it's changed while we were waiting for lock, do nothing */
+	if (!BUFFERTAGS_EQUAL(buf->tag, oldTag))
+	{
+		UnlockBufHdr(buf);
+		LWLockRelease(oldPartitionLock);
+		return;
+	}
+
+	/*
+	 * Validate wheather we can add the buffer into freelist or not
+	 */
+	if ((buf->refcount != 0) || (buf->usage_count != 0))
+	{
+		UnlockBufHdr(buf);
+		LWLockRelease(oldPartitionLock);
+		return;
+	}
+
+	/*
+	 * Clear out the buffer's tag and flags.  We must do this to ensure that
+	 * linear scans of the buffer array don't think the buffer is valid.
+	 */
+	oldFlags = buf->flags;
+	CLEAR_BUFFERTAG(buf->tag);
+	buf->flags = 0;
+	buf->usage_count = 0;
+
+	UnlockBufHdr(buf);
+
+	/*
+	 * Remove the buffer from the lookup hashtable, if it was in there.
+	 */
+	if (oldFlags & BM_TAG_VALID)
+		BufTableDelete(&oldTag, oldHash);
+
+	/*
+	 * Done with mapping lock.
+	 */
+	LWLockRelease(oldPartitionLock);
+
+	/*
+	 * Insert the buffer at the head of the list of free buffers.
+	 */
+	StrategyFreeBuffer(buf);
+}
+
 /*
  * MarkBufferDirty
  *
@@ -1658,12 +1740,29 @@ SyncOneBuffer(int buf_id, bool skip_recently_used)
 		return result;
 	}
 
-	if (!(bufHdr->flags & BM_VALID) || !(bufHdr->flags & BM_DIRTY))
+	if (!(bufHdr->flags & BM_VALID))
 	{
 		/* It's clean, so nothing to do */
 		UnlockBufHdr(bufHdr);
 		return result;
 	}
+	else if (!(bufHdr->flags & BM_DIRTY))
+	{
+		/*
+		 * It's clean, so nothing to flush;
+		 * if buffer is unused then move it to freelist
+		 */
+		if ((bufHdr->refcount == 0 && bufHdr->usage_count == 0)
+			&& (bufHdr->freeNext == FREENEXT_NOT_IN_LIST))
+		{
+			MoveBufferToFreeList (bufHdr);
+		}
+		else
+		{
+			UnlockBufHdr(bufHdr);
+		}
+		return result;
+	}
 
 	/*
 	 * Pin it, share-lock it, write it.  (FlushBuffer will do nothing if the
@@ -1677,6 +1776,19 @@ SyncOneBuffer(int buf_id, bool skip_recently_used)
 	LWLockRelease(bufHdr->content_lock);
 	UnpinBuffer(bufHdr, true);
 
+	/*
+	 * Buffer is unused then move it to freelist
+	 */
+	LockBufHdr(bufHdr);
+	if (bufHdr->refcount == 0 && bufHdr->usage_count == 0)
+	{
+		MoveBufferToFreeList (bufHdr);
+	}
+	else
+	{
+		UnlockBufHdr(bufHdr);
+	}
+
 	return result | BUF_WRITTEN;
 }