Refactor UnpinBuffer()

Started by Aleksander Alekseevover 3 years ago8 messages
#1Aleksander Alekseev
aleksander@timescale.com
1 attachment(s)

Hi hackers,

The proposed patch removes the redundant `fixOwner` argument.

"""
The fixOwner bool argument ended up always being true, so it doesn't do much
anymore. Removing it doesn't necessarily affect the performance a lot, but at
least improves the readability. The procedure is static thus the extension
authors are not going to be upset.
"""

--
Best regards,
Aleksander Alekseev

Attachments:

v1-0001-Refactor-UnpinBuffer.patchapplication/octet-stream; name=v1-0001-Refactor-UnpinBuffer.patchDownload
From 854f9e5e2df493b484f7daf946a36597a350a5c6 Mon Sep 17 00:00:00 2001
From: Aleksander Alekseev <aleksander@timescale.com>
Date: Wed, 28 Sep 2022 20:02:54 +0300
Subject: [PATCH v1] Refactor UnpinBuffer()

The fixOwner bool argument ended up always being true, so it doesn't do much
anymore. Removing it doesn't necessarily affect the performance a lot, but at
least improves the readability. The procedure is static thus the extension
authors are not going to be upset.

Aleksander Alekseev, reviewed by TODO FIXME
Discussion: TODO FIXME
---
 src/backend/storage/buffer/bufmgr.c | 34 +++++++++++++----------------
 1 file changed, 15 insertions(+), 19 deletions(-)

diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 5b0e531f97..93bfd751d4 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -465,7 +465,7 @@ static Buffer ReadBuffer_common(SMgrRelation smgr, char relpersistence,
 								bool *hit);
 static bool PinBuffer(BufferDesc *buf, BufferAccessStrategy strategy);
 static void PinBuffer_Locked(BufferDesc *buf);
-static void UnpinBuffer(BufferDesc *buf, bool fixOwner);
+static void UnpinBuffer(BufferDesc *buf);
 static void BufferSync(int flags);
 static uint32 WaitBufHdrUnlocked(BufferDesc *buf);
 static int	SyncOneBuffer(int buf_id, bool skip_recently_used,
@@ -1258,7 +1258,7 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 					{
 						/* Drop lock/pin and loop around for another buffer */
 						LWLockRelease(BufferDescriptorGetContentLock(buf));
-						UnpinBuffer(buf, true);
+						UnpinBuffer(buf);
 						continue;
 					}
 				}
@@ -1286,7 +1286,7 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 				 * Someone else has locked the buffer, so give it up and loop
 				 * back to get another one.
 				 */
-				UnpinBuffer(buf, true);
+				UnpinBuffer(buf);
 				continue;
 			}
 		}
@@ -1353,7 +1353,7 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 			 * pool in the first place.  First, give up the buffer we were
 			 * planning to use.
 			 */
-			UnpinBuffer(buf, true);
+			UnpinBuffer(buf);
 
 			/* Can give up that buffer's mapping partition lock now */
 			if (oldPartitionLock != NULL &&
@@ -1414,7 +1414,7 @@ BufferAlloc(SMgrRelation smgr, char relpersistence, ForkNumber forkNum,
 			oldPartitionLock != newPartitionLock)
 			LWLockRelease(oldPartitionLock);
 		LWLockRelease(newPartitionLock);
-		UnpinBuffer(buf, true);
+		UnpinBuffer(buf);
 	}
 
 	/*
@@ -1671,7 +1671,7 @@ ReleaseAndReadBuffer(Buffer buffer,
 				BufTagMatchesRelFileLocator(&bufHdr->tag, &relation->rd_locator) &&
 				BufTagGetForkNum(&bufHdr->tag) == forkNum)
 				return buffer;
-			UnpinBuffer(bufHdr, true);
+			UnpinBuffer(bufHdr);
 		}
 	}
 
@@ -1844,24 +1844,20 @@ PinBuffer_Locked(BufferDesc *buf)
  * UnpinBuffer -- make buffer available for replacement.
  *
  * This should be applied only to shared buffers, never local ones.
- *
- * Most but not all callers want CurrentResourceOwner to be adjusted.
- * Those that don't should pass fixOwner = false.
  */
 static void
-UnpinBuffer(BufferDesc *buf, bool fixOwner)
+UnpinBuffer(BufferDesc *buf)
 {
 	PrivateRefCountEntry *ref;
 	Buffer		b = BufferDescriptorGetBuffer(buf);
 
+	ResourceOwnerForgetBuffer(CurrentResourceOwner, b);
+
 	/* not moving as we're likely deleting it soon anyway */
 	ref = GetPrivateRefCountEntry(b, false);
 	Assert(ref != NULL);
-
-	if (fixOwner)
-		ResourceOwnerForgetBuffer(CurrentResourceOwner, b);
-
 	Assert(ref->refcount > 0);
+
 	ref->refcount--;
 	if (ref->refcount == 0)
 	{
@@ -2579,7 +2575,7 @@ SyncOneBuffer(int buf_id, bool skip_recently_used, WritebackContext *wb_context)
 
 	tag = bufHdr->tag;
 
-	UnpinBuffer(bufHdr, true);
+	UnpinBuffer(bufHdr);
 
 	ScheduleBufferTagForWriteback(wb_context, &tag);
 
@@ -3591,7 +3587,7 @@ FlushRelationBuffers(Relation rel)
 			LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED);
 			FlushBuffer(bufHdr, RelationGetSmgr(rel));
 			LWLockRelease(BufferDescriptorGetContentLock(bufHdr));
-			UnpinBuffer(bufHdr, true);
+			UnpinBuffer(bufHdr);
 		}
 		else
 			UnlockBufHdr(bufHdr, buf_state);
@@ -3689,7 +3685,7 @@ FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels)
 			LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED);
 			FlushBuffer(bufHdr, srelent->srel);
 			LWLockRelease(BufferDescriptorGetContentLock(bufHdr));
-			UnpinBuffer(bufHdr, true);
+			UnpinBuffer(bufHdr);
 		}
 		else
 			UnlockBufHdr(bufHdr, buf_state);
@@ -3899,7 +3895,7 @@ FlushDatabaseBuffers(Oid dbid)
 			LWLockAcquire(BufferDescriptorGetContentLock(bufHdr), LW_SHARED);
 			FlushBuffer(bufHdr, NULL);
 			LWLockRelease(BufferDescriptorGetContentLock(bufHdr));
-			UnpinBuffer(bufHdr, true);
+			UnpinBuffer(bufHdr);
 		}
 		else
 			UnlockBufHdr(bufHdr, buf_state);
@@ -3945,7 +3941,7 @@ ReleaseBuffer(Buffer buffer)
 		return;
 	}
 
-	UnpinBuffer(GetBufferDescriptor(buffer - 1), true);
+	UnpinBuffer(GetBufferDescriptor(buffer - 1));
 }
 
 /*
-- 
2.37.2

#2Nathan Bossart
nathandbossart@gmail.com
In reply to: Aleksander Alekseev (#1)
Re: Refactor UnpinBuffer()

On Wed, Sep 28, 2022 at 08:14:23PM +0300, Aleksander Alekseev wrote:

+       ResourceOwnerForgetBuffer(CurrentResourceOwner, b);
+
/* not moving as we're likely deleting it soon anyway */
ref = GetPrivateRefCountEntry(b, false);
Assert(ref != NULL);
-
-       if (fixOwner)
-               ResourceOwnerForgetBuffer(CurrentResourceOwner, b);

Is it safe to move the call to ResourceOwnerForgetBuffer() to before the
call to GetPrivateRefCountEntry()? From my quick skim of the code, it
seems like it should be safe, but I thought I'd ask the question.
Otherwise, LGTM.

--
Nathan Bossart
Amazon Web Services: https://aws.amazon.com

#3Zhang Mingli
zmlpostgres@gmail.com
In reply to: Nathan Bossart (#2)
Re: Refactor UnpinBuffer()

HI,

On Sep 29, 2022, 05:08 +0800, Nathan Bossart <nathandbossart@gmail.com>, wrote:

On Wed, Sep 28, 2022 at 08:14:23PM +0300, Aleksander Alekseev wrote:

+ ResourceOwnerForgetBuffer(CurrentResourceOwner, b);
+
/* not moving as we're likely deleting it soon anyway */
ref = GetPrivateRefCountEntry(b, false);
Assert(ref != NULL);
-
- if (fixOwner)
- ResourceOwnerForgetBuffer(CurrentResourceOwner, b);

+1, Good catch.

Is it safe to move the call to ResourceOwnerForgetBuffer() to before the
call to GetPrivateRefCountEntry()? From my quick skim of the code, it
seems like it should be safe, but I thought I'd ask the question.

Same question, have a look, it doesn’t seem to matter.

Regards,
Zhang Mingli

#4Aleksander Alekseev
aleksander@timescale.com
In reply to: Zhang Mingli (#3)
Re: Refactor UnpinBuffer()

Nathan, Zhang,

Thanks for the review!

Is it safe to move the call to ResourceOwnerForgetBuffer() to before the
call to GetPrivateRefCountEntry()? From my quick skim of the code, it
seems like it should be safe, but I thought I'd ask the question.

Same question, have a look, it doesn’t seem to matter.

Yep, I had some doubts here as well but it seems to be safe.

--
Best regards,
Aleksander Alekseev

#5Bharath Rupireddy
bharath.rupireddyforpostgres@gmail.com
In reply to: Aleksander Alekseev (#4)
Re: Refactor UnpinBuffer()

On Thu, Sep 29, 2022 at 1:52 PM Aleksander Alekseev
<aleksander@timescale.com> wrote:

Is it safe to move the call to ResourceOwnerForgetBuffer() to before the
call to GetPrivateRefCountEntry()? From my quick skim of the code, it
seems like it should be safe, but I thought I'd ask the question.

Same question, have a look, it doesn’t seem to matter.

Yep, I had some doubts here as well but it seems to be safe.

The commit 2d115e47c861878669ba0814b3d97a4e4c347e8b that removed the
last UnpinBuffer() call with fixOwner as false in ReleaseBuffer().
This commit is pretty old and +1 for removing the unused function
parameter.

Also, it looks like changing the order of GetPrivateRefCountEntry()
and ResourceOwnerForgetBuffer() doesn't have any effect as they are
independent, but do we want to actually do that if there's no specific
reason?

--
Bharath Rupireddy
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

#6Aleksander Alekseev
aleksander@timescale.com
In reply to: Bharath Rupireddy (#5)
Re: Refactor UnpinBuffer()

Hi Bharath,

Also, it looks like changing the order of GetPrivateRefCountEntry()
and ResourceOwnerForgetBuffer() doesn't have any effect as they are
independent, but do we want to actually do that if there's no specific
reason?

If we keep the order as it is now the code will become:

```
ref = GetPrivateRefCountEntry(b, false);
Assert(ref != NULL);

ResourceOwnerForgetBuffer(CurrentResourceOwner, b);

Assert(ref->refcount > 0);
ref->refcount--;
if (ref->refcount == 0)
```

I figured it would not hurt to gather all the calls and Asserts
related to `ref` together. This is the only reason why I choose to
rearrange the order of the calls in the patch.

So, no strong opinion in this respect from my side. I'm fine with
keeping the existing order.

--
Best regards,
Aleksander Alekseev

#7Nathan Bossart
nathandbossart@gmail.com
In reply to: Aleksander Alekseev (#6)
Re: Refactor UnpinBuffer()

I've marked this one as ready-for-committer.

--
Nathan Bossart
Amazon Web Services: https://aws.amazon.com

#8Michael Paquier
michael@paquier.xyz
In reply to: Nathan Bossart (#7)
Re: Refactor UnpinBuffer()

On Thu, Sep 29, 2022 at 10:35:20AM -0700, Nathan Bossart wrote:

I've marked this one as ready-for-committer.

UnpinBuffer() is local to bufmgr.c, so it would not be an issue for
external code, and that's 10 callers that don't need to worry about
that anymore. 2d115e4 is from 2015, and nobody has used this option
since, additionally.

Anyway, per the rule of consistency with the surroundings (see
ReleaseBuffer() and ReleaseAndReadBuffer()), it seems to me that there
is a good case for keeping the adjustment of CurrentResourceOwner
before any refcount checks. I have also kept a mention to
CurrentResourceOwner in the top comment of the function, and applied
that.
--
Michael