From 1b3d400cac138c12dd3d1428a9da112b69ad0f15 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 23 Sep 2007 18:50:38 +0000
Subject: [PATCH] TransactionIdIsInProgress can skip scanning the ProcArray if
 the target XID is later than latestCompletedXid, per Florian Pflug.  Also
 some minor improvements in the XIDCACHE_DEBUG code --- make sure each call of
 TransactionIdIsInProgress is counted one way or another.

---
 src/backend/storage/ipc/procarray.c | 34 ++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index dbac4a8fd05..90ba09d5a88 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -23,7 +23,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.34 2007/09/21 17:36:53 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.35 2007/09/23 18:50:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -61,14 +61,18 @@ static ProcArrayStruct *procArray;
 /* counters for XidCache measurement */
 static long xc_by_recent_xmin = 0;
 static long xc_by_my_xact = 0;
+static long xc_by_latest_xid = 0;
 static long xc_by_main_xid = 0;
 static long xc_by_child_xid = 0;
+static long xc_no_overflow = 0;
 static long xc_slow_answer = 0;
 
 #define xc_by_recent_xmin_inc()		(xc_by_recent_xmin++)
 #define xc_by_my_xact_inc()			(xc_by_my_xact++)
+#define xc_by_latest_xid_inc()		(xc_by_latest_xid++)
 #define xc_by_main_xid_inc()		(xc_by_main_xid++)
 #define xc_by_child_xid_inc()		(xc_by_child_xid++)
+#define xc_no_overflow_inc()		(xc_no_overflow++)
 #define xc_slow_answer_inc()		(xc_slow_answer++)
 
 static void DisplayXidCache(void);
@@ -76,8 +80,10 @@ static void DisplayXidCache(void);
 
 #define xc_by_recent_xmin_inc()		((void) 0)
 #define xc_by_my_xact_inc()			((void) 0)
+#define xc_by_latest_xid_inc()		((void) 0)
 #define xc_by_main_xid_inc()		((void) 0)
 #define xc_by_child_xid_inc()		((void) 0)
+#define xc_no_overflow_inc()		((void) 0)
 #define xc_slow_answer_inc()		((void) 0)
 #endif   /* XIDCACHE_DEBUG */
 
@@ -302,7 +308,8 @@ ProcArrayClearTransaction(PGPROC *proc)
 /*
  * TransactionIdIsInProgress -- is given transaction running in some backend
  *
- * There are three possibilities for finding a running transaction:
+ * Aside from some shortcuts such as checking RecentXmin and our own Xid,
+ * there are three possibilities for finding a running transaction:
  *
  * 1. the given Xid is a main transaction Id.  We will find this out cheaply
  * by looking at the PGPROC struct for each backend.
@@ -368,6 +375,18 @@ TransactionIdIsInProgress(TransactionId xid)
 
 	LWLockAcquire(ProcArrayLock, LW_SHARED);
 
+	/*
+	 * Now that we have the lock, we can check latestCompletedXid; if the
+	 * target Xid is after that, it's surely still running.
+	 */
+	if (TransactionIdPrecedes(ShmemVariableCache->latestCompletedXid, xid))
+	{
+		LWLockRelease(ProcArrayLock);
+		xc_by_latest_xid_inc();
+		return true;
+	}
+
+	/* No shortcuts, gotta grovel through the array */
 	for (i = 0; i < arrayP->numProcs; i++)
 	{
 		volatile PGPROC	   *proc = arrayP->procs[i];
@@ -434,7 +453,10 @@ TransactionIdIsInProgress(TransactionId xid)
 	 * running without looking at pg_subtrans.
 	 */
 	if (nxids == 0)
+	{
+		xc_no_overflow_inc();
 		return false;
+	}
 
 	/*
 	 * Step 3: have to check pg_subtrans.
@@ -451,8 +473,8 @@ TransactionIdIsInProgress(TransactionId xid)
 
 	/*
 	 * It isn't aborted, so check whether the transaction tree it belongs to
-	 * is still running (or, more precisely, whether it was running when this
-	 * routine started -- note that we already released ProcArrayLock).
+	 * is still running (or, more precisely, whether it was running when
+	 * we held ProcArrayLock).
 	 */
 	topxid = SubTransGetTopmostTransaction(xid);
 	Assert(TransactionIdIsValid(topxid));
@@ -1300,11 +1322,13 @@ static void
 DisplayXidCache(void)
 {
 	fprintf(stderr,
-			"XidCache: xmin: %ld, myxact: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n",
+			"XidCache: xmin: %ld, myxact: %ld, latest: %ld, mainxid: %ld, childxid: %ld, nooflo: %ld, slow: %ld\n",
 			xc_by_recent_xmin,
 			xc_by_my_xact,
+			xc_by_latest_xid,
 			xc_by_main_xid,
 			xc_by_child_xid,
+			xc_no_overflow,
 			xc_slow_answer);
 }
 
-- 
GitLab