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:
parent
bd0af827da
commit
da072ab2ab
|
@ -23,7 +23,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 */
|
/* counters for XidCache measurement */
|
||||||
static long xc_by_recent_xmin = 0;
|
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_main_xid = 0;
|
||||||
static long xc_by_child_xid = 0;
|
static long xc_by_child_xid = 0;
|
||||||
static long xc_slow_answer = 0;
|
static long xc_slow_answer = 0;
|
||||||
|
|
||||||
#define xc_by_recent_xmin_inc() (xc_by_recent_xmin++)
|
#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_main_xid_inc() (xc_by_main_xid++)
|
||||||
#define xc_by_child_xid_inc() (xc_by_child_xid++)
|
#define xc_by_child_xid_inc() (xc_by_child_xid++)
|
||||||
#define xc_slow_answer_inc() (xc_slow_answer++)
|
#define xc_slow_answer_inc() (xc_slow_answer++)
|
||||||
|
@ -73,6 +75,7 @@ static void DisplayXidCache(void);
|
||||||
#else /* !XIDCACHE_DEBUG */
|
#else /* !XIDCACHE_DEBUG */
|
||||||
|
|
||||||
#define xc_by_recent_xmin_inc() ((void) 0)
|
#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_main_xid_inc() ((void) 0)
|
||||||
#define xc_by_child_xid_inc() ((void) 0)
|
#define xc_by_child_xid_inc() ((void) 0)
|
||||||
#define xc_slow_answer_inc() ((void) 0)
|
#define xc_slow_answer_inc() ((void) 0)
|
||||||
|
@ -320,14 +323,12 @@ ProcArrayClearTransaction(PGPROC *proc)
|
||||||
bool
|
bool
|
||||||
TransactionIdIsInProgress(TransactionId xid)
|
TransactionIdIsInProgress(TransactionId xid)
|
||||||
{
|
{
|
||||||
bool result = false;
|
static TransactionId *xids = NULL;
|
||||||
|
int nxids = 0;
|
||||||
ProcArrayStruct *arrayP = procArray;
|
ProcArrayStruct *arrayP = procArray;
|
||||||
|
TransactionId topxid;
|
||||||
int i,
|
int i,
|
||||||
j;
|
j;
|
||||||
int nxids = 0;
|
|
||||||
TransactionId *xids;
|
|
||||||
TransactionId topxid;
|
|
||||||
bool locked;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't bother checking a transaction older than RecentXmin; it could not
|
* Don't bother checking a transaction older than RecentXmin; it could not
|
||||||
|
@ -341,18 +342,43 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||||
return false;
|
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);
|
LWLockAcquire(ProcArrayLock, LW_SHARED);
|
||||||
locked = true;
|
|
||||||
|
|
||||||
for (i = 0; i < arrayP->numProcs; i++)
|
for (i = 0; i < arrayP->numProcs; i++)
|
||||||
{
|
{
|
||||||
volatile PGPROC *proc = arrayP->procs[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 */
|
/* Fetch xid just once - see GetNewTransactionId */
|
||||||
TransactionId pxid = proc->xid;
|
pxid = proc->xid;
|
||||||
|
|
||||||
if (!TransactionIdIsValid(pxid))
|
if (!TransactionIdIsValid(pxid))
|
||||||
continue;
|
continue;
|
||||||
|
@ -362,9 +388,9 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||||
*/
|
*/
|
||||||
if (TransactionIdEquals(pxid, xid))
|
if (TransactionIdEquals(pxid, xid))
|
||||||
{
|
{
|
||||||
|
LWLockRelease(ProcArrayLock);
|
||||||
xc_by_main_xid_inc();
|
xc_by_main_xid_inc();
|
||||||
result = true;
|
return true;
|
||||||
goto result_known;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -384,9 +410,9 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||||
|
|
||||||
if (TransactionIdEquals(cxid, xid))
|
if (TransactionIdEquals(cxid, xid))
|
||||||
{
|
{
|
||||||
|
LWLockRelease(ProcArrayLock);
|
||||||
xc_by_child_xid_inc();
|
xc_by_child_xid_inc();
|
||||||
result = true;
|
return true;
|
||||||
goto result_known;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,14 +428,13 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||||
}
|
}
|
||||||
|
|
||||||
LWLockRelease(ProcArrayLock);
|
LWLockRelease(ProcArrayLock);
|
||||||
locked = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If none of the relevant caches overflowed, we know the Xid is not
|
* If none of the relevant caches overflowed, we know the Xid is not
|
||||||
* running without looking at pg_subtrans.
|
* running without looking at pg_subtrans.
|
||||||
*/
|
*/
|
||||||
if (nxids == 0)
|
if (nxids == 0)
|
||||||
goto result_known;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Step 3: have to check pg_subtrans.
|
* Step 3: have to check pg_subtrans.
|
||||||
|
@ -422,7 +447,7 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||||
xc_slow_answer_inc();
|
xc_slow_answer_inc();
|
||||||
|
|
||||||
if (TransactionIdDidAbort(xid))
|
if (TransactionIdDidAbort(xid))
|
||||||
goto result_known;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It isn't aborted, so check whether the transaction tree it belongs to
|
* 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++)
|
for (i = 0; i < nxids; i++)
|
||||||
{
|
{
|
||||||
if (TransactionIdEquals(xids[i], topxid))
|
if (TransactionIdEquals(xids[i], topxid))
|
||||||
{
|
return true;
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result_known:
|
return false;
|
||||||
if (locked)
|
|
||||||
LWLockRelease(ProcArrayLock);
|
|
||||||
|
|
||||||
pfree(xids);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1284,8 +1300,9 @@ static void
|
||||||
DisplayXidCache(void)
|
DisplayXidCache(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr,
|
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_recent_xmin,
|
||||||
|
xc_by_my_xact,
|
||||||
xc_by_main_xid,
|
xc_by_main_xid,
|
||||||
xc_by_child_xid,
|
xc_by_child_xid,
|
||||||
xc_slow_answer);
|
xc_slow_answer);
|
||||||
|
|
Loading…
Reference in New Issue