]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Make some simple performance improvements in TransactionIdIsInProgress().
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 21 Sep 2007 17:36:53 +0000 (17:36 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 21 Sep 2007 17:36:53 +0000 (17:36 +0000)
For XIDs of our own transaction and subtransactions, it's cheaper to ask
TransactionIdIsCurrentTransactionId() than to look in shared memory.
Also, the xids[] work array is always the same size within any given
process, so malloc it just once instead of doing a palloc/pfree on every
call; aside from being faster this lets us get rid of some goto's, since
we no longer have any end-of-function pfree to do.  Both ideas by Heikki.

src/backend/storage/ipc/procarray.c

index 0565510c31b8676a9d8018b5fe45e1595e6ab859..dbac4a8fd05de662eda005deb1a8bffc98253c3c 100644 (file)
@@ -23,7 +23,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.33 2007/09/08 20:31:15 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.34 2007/09/21 17:36:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,11 +60,13 @@ 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_main_xid = 0;
 static long xc_by_child_xid = 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_main_xid_inc()           (xc_by_main_xid++)
 #define xc_by_child_xid_inc()          (xc_by_child_xid++)
 #define xc_slow_answer_inc()           (xc_slow_answer++)
@@ -73,6 +75,7 @@ static void DisplayXidCache(void);
 #else                                                  /* !XIDCACHE_DEBUG */
 
 #define xc_by_recent_xmin_inc()                ((void) 0)
+#define xc_by_my_xact_inc()                    ((void) 0)
 #define xc_by_main_xid_inc()           ((void) 0)
 #define xc_by_child_xid_inc()          ((void) 0)
 #define xc_slow_answer_inc()           ((void) 0)
@@ -320,14 +323,12 @@ ProcArrayClearTransaction(PGPROC *proc)
 bool
 TransactionIdIsInProgress(TransactionId xid)
 {
-       bool            result = false;
+       static TransactionId *xids = NULL;
+       int                     nxids = 0;
        ProcArrayStruct *arrayP = procArray;
+       TransactionId topxid;
        int                     i,
                                j;
-       int                     nxids = 0;
-       TransactionId *xids;
-       TransactionId topxid;
-       bool            locked;
 
        /*
         * Don't bother checking a transaction older than RecentXmin; it could not
@@ -341,18 +342,43 @@ TransactionIdIsInProgress(TransactionId xid)
                return false;
        }
 
-       /* Get workspace to remember main XIDs in */
-       xids = (TransactionId *) palloc(sizeof(TransactionId) * arrayP->maxProcs);
+       /*
+        * Also, we can handle our own transaction (and subtransactions) without
+        * any access to shared memory.
+        */
+       if (TransactionIdIsCurrentTransactionId(xid))
+       {
+               xc_by_my_xact_inc();
+               return true;
+       }
+
+       /*
+        * If not first time through, get workspace to remember main XIDs in.
+        * We malloc it permanently to avoid repeated palloc/pfree overhead.
+        */
+       if (xids == NULL)
+       {
+               xids = (TransactionId *)
+                       malloc(arrayP->maxProcs * sizeof(TransactionId));
+               if (xids == NULL)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_OUT_OF_MEMORY),
+                                        errmsg("out of memory")));
+       }
 
        LWLockAcquire(ProcArrayLock, LW_SHARED);
-       locked = true;
 
        for (i = 0; i < arrayP->numProcs; i++)
        {
                volatile PGPROC    *proc = arrayP->procs[i];
+               TransactionId pxid;
+
+               /* Ignore my own proc --- dealt with it above */
+               if (proc == MyProc)
+                       continue;
 
                /* Fetch xid just once - see GetNewTransactionId */
-               TransactionId pxid = proc->xid;
+               pxid = proc->xid;
 
                if (!TransactionIdIsValid(pxid))
                        continue;
@@ -362,9 +388,9 @@ TransactionIdIsInProgress(TransactionId xid)
                 */
                if (TransactionIdEquals(pxid, xid))
                {
+                       LWLockRelease(ProcArrayLock);
                        xc_by_main_xid_inc();
-                       result = true;
-                       goto result_known;
+                       return true;
                }
 
                /*
@@ -384,9 +410,9 @@ TransactionIdIsInProgress(TransactionId xid)
 
                        if (TransactionIdEquals(cxid, xid))
                        {
+                               LWLockRelease(ProcArrayLock);
                                xc_by_child_xid_inc();
-                               result = true;
-                               goto result_known;
+                               return true;
                        }
                }
 
@@ -402,14 +428,13 @@ TransactionIdIsInProgress(TransactionId xid)
        }
 
        LWLockRelease(ProcArrayLock);
-       locked = false;
 
        /*
         * If none of the relevant caches overflowed, we know the Xid is not
         * running without looking at pg_subtrans.
         */
        if (nxids == 0)
-               goto result_known;
+               return false;
 
        /*
         * Step 3: have to check pg_subtrans.
@@ -422,7 +447,7 @@ TransactionIdIsInProgress(TransactionId xid)
        xc_slow_answer_inc();
 
        if (TransactionIdDidAbort(xid))
-               goto result_known;
+               return false;
 
        /*
         * It isn't aborted, so check whether the transaction tree it belongs to
@@ -436,20 +461,11 @@ TransactionIdIsInProgress(TransactionId xid)
                for (i = 0; i < nxids; i++)
                {
                        if (TransactionIdEquals(xids[i], topxid))
-                       {
-                               result = true;
-                               break;
-                       }
+                               return true;
                }
        }
 
-result_known:
-       if (locked)
-               LWLockRelease(ProcArrayLock);
-
-       pfree(xids);
-
-       return result;
+       return false;
 }
 
 /*
@@ -1284,8 +1300,9 @@ static void
 DisplayXidCache(void)
 {
        fprintf(stderr,
-                       "XidCache: xmin: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n",
+                       "XidCache: xmin: %ld, myxact: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n",
                        xc_by_recent_xmin,
+                       xc_by_my_xact,
                        xc_by_main_xid,
                        xc_by_child_xid,
                        xc_slow_answer);