Commit da072ab2 authored by Tom Lane's avatar Tom Lane

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.
parent bd0af827
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment