We currently have a single item cache of the last checked TransactionId,
which optimises the call to TransactionIdDidCommit() during
HeapTupleSatisfiesMVCC() and partners.
Before we call TransactionIdDidCommit() we always call
TransactionIdIsInProgress().
TransactionIdIsInProgress() doesn't check the single item cache, so even
if we have just checked for this xid, we will check it again. Since this
function takes ProcArrayLock and may be called while holding other locks
it will improve scalability if we can skip the call, for the cost of an
integer comparison.
Following patch implements fastpath in TransactionIdIsInProgress() to
utilise single item cache.
--
Simon Riggs
2ndQuadrant http://www.2ndQuadrant.com
Index: src/backend/access/transam/transam.c
===
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/access/transam/transam.c,v
retrieving revision 1.73
diff -c -r1.73 transam.c
*** src/backend/access/transam/transam.c 1 Jan 2008 19:45:48 - 1.73
--- src/backend/access/transam/transam.c 5 Feb 2008 12:21:51 -
***
*** 262,267
--- 262,283
return false;
}
+ bool
+ TransactionIdIsKnownNotInProgress(TransactionId transactionId)
+ {
+ if (TransactionIdEquals(transactionId, cachedFetchXid))
+ {
+ switch (cachedFetchXidStatus)
+ {
+ case TRANSACTION_STATUS_COMMITTED:
+ case TRANSACTION_STATUS_ABORTED:
+ return true;
+ }
+ }
+
+ return false;
+ }
+
/*
* TransactionId Commit
* TransactionId Abort
Index: src/backend/storage/ipc/procarray.c
===
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/storage/ipc/procarray.c,v
retrieving revision 1.40
diff -c -r1.40 procarray.c
*** src/backend/storage/ipc/procarray.c 9 Jan 2008 21:52:36 - 1.40
--- src/backend/storage/ipc/procarray.c 5 Feb 2008 12:21:12 -
***
*** 61,66
--- 61,67
/* counters for XidCache measurement */
static long xc_by_recent_xmin = 0;
static long xc_by_my_xact = 0;
+ static long xc_by_known_xact = 0;
static long xc_by_latest_xid = 0;
static long xc_by_main_xid = 0;
static long xc_by_child_xid = 0;
***
*** 69,74
--- 70,76
#define xc_by_recent_xmin_inc() (xc_by_recent_xmin++)
#define xc_by_my_xact_inc() (xc_by_my_xact++)
+ #define xc_by_known_xact_inc() (xc_by_known_xact++)
#define xc_by_latest_xid_inc() (xc_by_latest_xid++)
#define xc_by_main_xid_inc() (xc_by_main_xid++)
#define xc_by_child_xid_inc() (xc_by_child_xid++)
***
*** 80,85
--- 82,88
#define xc_by_recent_xmin_inc() ((void) 0)
#define xc_by_my_xact_inc() ((void) 0)
+ #define xc_by_known_xact_inc() ((void) 0)
#define xc_by_latest_xid_inc() ((void) 0)
#define xc_by_main_xid_inc() ((void) 0)
#define xc_by_child_xid_inc() ((void) 0)
***
*** 364,369
--- 367,382
}
/*
+ * We may have just checked the status of this transaction, so if it is
+ * already known to be not in progress, take a fastpath out
+ */
+ if (TransactionIdIsKnownNotInProgress(xid))
+ {
+ xc_by_known_xact_inc();
+ return false;
+ }
+
+ /*
* If not first time through, get workspace to remember main XIDs in. We
* malloc it permanently to avoid repeated palloc/pfree overhead.
*/
***
*** 1335,1343
DisplayXidCache(void)
{
fprintf(stderr,
! "XidCache: xmin: %ld, myxact: %ld, latest: %ld, mainxid: %ld, childxid: %ld, nooflo: %ld, slow: %ld\n",
xc_by_recent_xmin,
xc_by_my_xact,
xc_by_latest_xid,
xc_by_main_xid,
xc_by_child_xid,
--- 1348,1357
DisplayXidCache(void)
{
fprintf(stderr,
! "XidCache: xmin: %ld, myxact: %ld, known: %ld, latest: %ld, mainxid: %ld, childxid: %ld, nooflo: %ld, slow: %ld\n",
xc_by_recent_xmin,
xc_by_my_xact,
+ xc_by_known_xact,
xc_by_latest_xid,
xc_by_main_xid,
xc_by_child_xid,
Index: src/include/access/transam.h
===
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/access/transam.h,v
retrieving revision 1.64
diff -c -r1.64 transam.h
*** src/include/access/transam.h 1 Jan 2008 19:45:56 - 1.64
--- src/include/access/transam.h 5 Feb 2008 12:21:12 -
***
*** 138,143
--- 138,144
*/
extern bool TransactionIdDidCommit(TransactionId transactionId);
extern bool TransactionIdDidAbort(TransactionId transactionId);
+ extern bool TransactionIdIsKnownNotInProgress(TransactionId transactionId);
extern void TransactionIdCommit(TransactionId transactionId);
extern void TransactionIdAsyncCommit(TransactionId transactionId, XLogRecPtr lsn);
extern void TransactionIdAbort(TransactionId transactionId);
---(end of broadcast)---
TIP 1: if posting/reading through Usenet, pl