mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-12 18:34:36 +08:00
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
|
||||
* $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);
|
||||
|
Loading…
Reference in New Issue
Block a user