From a4b09af3e93707351f1d4b8efafabfa135c0f70b Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Fri, 31 Jul 2015 20:50:35 +0200
Subject: [PATCH] Micro optimize LWLockAttemptLock() a bit.

LWLockAttemptLock pointlessly read the lock's state in every loop
iteration, even though pg_atomic_compare_exchange_u32() returns the old
value. Instead do that only once before the loop iteration.

Additionally there's no need to have the expected_state variable,
old_state mostly had the same value anyway.

Noticed-By: Heikki Linnakangas
Backpatch: 9.5, no reason to let the branches diverge at this point
---
 src/backend/storage/lmgr/lwlock.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index ae03eb14196..687ed6399cb 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -582,29 +582,33 @@ LWLockInitialize(LWLock *lock, int tranche_id)
 static bool
 LWLockAttemptLock(LWLock *lock, LWLockMode mode)
 {
+	uint32		old_state;
+
 	AssertArg(mode == LW_EXCLUSIVE || mode == LW_SHARED);
 
+	/*
+	 * Read once outside the loop, later iterations will get the newer value
+	 * via compare & exchange.
+	 */
+	old_state = pg_atomic_read_u32(&lock->state);
+
 	/* loop until we've determined whether we could acquire the lock or not */
 	while (true)
 	{
-		uint32		old_state;
-		uint32		expected_state;
 		uint32		desired_state;
 		bool		lock_free;
 
-		old_state = pg_atomic_read_u32(&lock->state);
-		expected_state = old_state;
-		desired_state = expected_state;
+		desired_state = old_state;
 
 		if (mode == LW_EXCLUSIVE)
 		{
-			lock_free = (expected_state & LW_LOCK_MASK) == 0;
+			lock_free = (old_state & LW_LOCK_MASK) == 0;
 			if (lock_free)
 				desired_state += LW_VAL_EXCLUSIVE;
 		}
 		else
 		{
-			lock_free = (expected_state & LW_VAL_EXCLUSIVE) == 0;
+			lock_free = (old_state & LW_VAL_EXCLUSIVE) == 0;
 			if (lock_free)
 				desired_state += LW_VAL_SHARED;
 		}
@@ -620,7 +624,7 @@ LWLockAttemptLock(LWLock *lock, LWLockMode mode)
 		 * Retry if the value changed since we last looked at it.
 		 */
 		if (pg_atomic_compare_exchange_u32(&lock->state,
-										   &expected_state, desired_state))
+										   &old_state, desired_state))
 		{
 			if (lock_free)
 			{
-- 
GitLab