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.
This commit is contained in:
Tom Lane 2007-09-21 17:36:53 +00:00
parent bd0af827da
commit da072ab2ab
1 changed files with 46 additions and 29 deletions

View 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);