summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-09-21 17:36:53 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-09-21 17:36:53 +0000
commitda072ab2ab538bf1811abe5a1df131c0c9a8e6e4 (patch)
tree664ebca17e65551f70cc0dce22fedc2aa9094849 /src
parentbd0af827da5f5c648cb7530bb7157a24d8bd7a07 (diff)
Make some simple performance improvements in TransactionIdIsInProgress().
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/ipc/procarray.c75
1 files changed, 46 insertions, 29 deletions
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 0565510c31b..dbac4a8fd05 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.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);