Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit da072ab

Browse files
committed
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.
1 parent bd0af82 commit da072ab

File tree

1 file changed

+46
-29
lines changed

1 file changed

+46
-29
lines changed

src/backend/storage/ipc/procarray.c

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
*
2424
*
2525
* IDENTIFICATION
26-
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.33 2007/09/08 20:31:15 tgl Exp $
26+
* $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.34 2007/09/21 17:36:53 tgl Exp $
2727
*
2828
*-------------------------------------------------------------------------
2929
*/
@@ -60,11 +60,13 @@ static ProcArrayStruct *procArray;
6060

6161
/* counters for XidCache measurement */
6262
static long xc_by_recent_xmin = 0;
63+
static long xc_by_my_xact = 0;
6364
static long xc_by_main_xid = 0;
6465
static long xc_by_child_xid = 0;
6566
static long xc_slow_answer = 0;
6667

6768
#define xc_by_recent_xmin_inc() (xc_by_recent_xmin++)
69+
#define xc_by_my_xact_inc() (xc_by_my_xact++)
6870
#define xc_by_main_xid_inc() (xc_by_main_xid++)
6971
#define xc_by_child_xid_inc() (xc_by_child_xid++)
7072
#define xc_slow_answer_inc() (xc_slow_answer++)
@@ -73,6 +75,7 @@ static void DisplayXidCache(void);
7375
#else /* !XIDCACHE_DEBUG */
7476

7577
#define xc_by_recent_xmin_inc() ((void) 0)
78+
#define xc_by_my_xact_inc() ((void) 0)
7679
#define xc_by_main_xid_inc() ((void) 0)
7780
#define xc_by_child_xid_inc() ((void) 0)
7881
#define xc_slow_answer_inc() ((void) 0)
@@ -320,14 +323,12 @@ ProcArrayClearTransaction(PGPROC *proc)
320323
bool
321324
TransactionIdIsInProgress(TransactionId xid)
322325
{
323-
bool result = false;
326+
static TransactionId *xids = NULL;
327+
int nxids = 0;
324328
ProcArrayStruct *arrayP = procArray;
329+
TransactionId topxid;
325330
int i,
326331
j;
327-
int nxids = 0;
328-
TransactionId *xids;
329-
TransactionId topxid;
330-
bool locked;
331332

332333
/*
333334
* Don't bother checking a transaction older than RecentXmin; it could not
@@ -341,18 +342,43 @@ TransactionIdIsInProgress(TransactionId xid)
341342
return false;
342343
}
343344

344-
/* Get workspace to remember main XIDs in */
345-
xids = (TransactionId *) palloc(sizeof(TransactionId) * arrayP->maxProcs);
345+
/*
346+
* Also, we can handle our own transaction (and subtransactions) without
347+
* any access to shared memory.
348+
*/
349+
if (TransactionIdIsCurrentTransactionId(xid))
350+
{
351+
xc_by_my_xact_inc();
352+
return true;
353+
}
354+
355+
/*
356+
* If not first time through, get workspace to remember main XIDs in.
357+
* We malloc it permanently to avoid repeated palloc/pfree overhead.
358+
*/
359+
if (xids == NULL)
360+
{
361+
xids = (TransactionId *)
362+
malloc(arrayP->maxProcs * sizeof(TransactionId));
363+
if (xids == NULL)
364+
ereport(ERROR,
365+
(errcode(ERRCODE_OUT_OF_MEMORY),
366+
errmsg("out of memory")));
367+
}
346368

347369
LWLockAcquire(ProcArrayLock, LW_SHARED);
348-
locked = true;
349370

350371
for (i = 0; i < arrayP->numProcs; i++)
351372
{
352373
volatile PGPROC *proc = arrayP->procs[i];
374+
TransactionId pxid;
375+
376+
/* Ignore my own proc --- dealt with it above */
377+
if (proc == MyProc)
378+
continue;
353379

354380
/* Fetch xid just once - see GetNewTransactionId */
355-
TransactionId pxid = proc->xid;
381+
pxid = proc->xid;
356382

357383
if (!TransactionIdIsValid(pxid))
358384
continue;
@@ -362,9 +388,9 @@ TransactionIdIsInProgress(TransactionId xid)
362388
*/
363389
if (TransactionIdEquals(pxid, xid))
364390
{
391+
LWLockRelease(ProcArrayLock);
365392
xc_by_main_xid_inc();
366-
result = true;
367-
goto result_known;
393+
return true;
368394
}
369395

370396
/*
@@ -384,9 +410,9 @@ TransactionIdIsInProgress(TransactionId xid)
384410

385411
if (TransactionIdEquals(cxid, xid))
386412
{
413+
LWLockRelease(ProcArrayLock);
387414
xc_by_child_xid_inc();
388-
result = true;
389-
goto result_known;
415+
return true;
390416
}
391417
}
392418

@@ -402,14 +428,13 @@ TransactionIdIsInProgress(TransactionId xid)
402428
}
403429

404430
LWLockRelease(ProcArrayLock);
405-
locked = false;
406431

407432
/*
408433
* If none of the relevant caches overflowed, we know the Xid is not
409434
* running without looking at pg_subtrans.
410435
*/
411436
if (nxids == 0)
412-
goto result_known;
437+
return false;
413438

414439
/*
415440
* Step 3: have to check pg_subtrans.
@@ -422,7 +447,7 @@ TransactionIdIsInProgress(TransactionId xid)
422447
xc_slow_answer_inc();
423448

424449
if (TransactionIdDidAbort(xid))
425-
goto result_known;
450+
return false;
426451

427452
/*
428453
* It isn't aborted, so check whether the transaction tree it belongs to
@@ -436,20 +461,11 @@ TransactionIdIsInProgress(TransactionId xid)
436461
for (i = 0; i < nxids; i++)
437462
{
438463
if (TransactionIdEquals(xids[i], topxid))
439-
{
440-
result = true;
441-
break;
442-
}
464+
return true;
443465
}
444466
}
445467

446-
result_known:
447-
if (locked)
448-
LWLockRelease(ProcArrayLock);
449-
450-
pfree(xids);
451-
452-
return result;
468+
return false;
453469
}
454470

455471
/*
@@ -1284,8 +1300,9 @@ static void
12841300
DisplayXidCache(void)
12851301
{
12861302
fprintf(stderr,
1287-
"XidCache: xmin: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n",
1303+
"XidCache: xmin: %ld, myxact: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n",
12881304
xc_by_recent_xmin,
1305+
xc_by_my_xact,
12891306
xc_by_main_xid,
12901307
xc_by_child_xid,
12911308
xc_slow_answer);

0 commit comments

Comments
 (0)