Add single-item cache when looking at topmost XID of a subtrans XID
authorMichael Paquier <[email protected]>
Thu, 7 Apr 2022 05:34:37 +0000 (14:34 +0900)
committerMichael Paquier <[email protected]>
Thu, 7 Apr 2022 05:34:37 +0000 (14:34 +0900)
This change affects SubTransGetTopmostTransaction(), used to find the
topmost transaction ID of a given transaction ID.  The cache is able to
store one value, so as we can save the backend from unnecessary lookups
at pg_subtrans/ on repetitive calls of this routine.  There is a similar
practice in transam.c, for example.

Author: Simon Riggs
Reviewed-by: Andrey Borodin, Julien Rouhaud
Discussion: https://postgr.es/m/CANbhV-G8Co=yq4v4BkW7MJDqVt68K_8A48nAZ_+8UQS7LrwLEQ@mail.gmail.com

src/backend/access/transam/subtrans.c

index 66d3548155248b2cdb9cba16a01344885d1103fb..7240454ca4e5b33d1d2acfa487a713512c9e4160 100644 (file)
 #define TransactionIdToPage(xid) ((xid) / (TransactionId) SUBTRANS_XACTS_PER_PAGE)
 #define TransactionIdToEntry(xid) ((xid) % (TransactionId) SUBTRANS_XACTS_PER_PAGE)
 
+/*
+ * Single-item cache for results of SubTransGetTopmostTransaction().  It's
+ * worth having such a cache because we frequently find ourselves repeatedly
+ * checking the same XID, for example when scanning a table just after a
+ * bulk insert, update, or delete.
+ */
+static TransactionId cachedFetchSubXid = InvalidTransactionId;
+static TransactionId cachedFetchTopmostXid = InvalidTransactionId;
 
 /*
  * Link to shared-memory data structures for SUBTRANS control
@@ -155,6 +163,13 @@ SubTransGetTopmostTransaction(TransactionId xid)
        /* Can't ask about stuff that might not be around anymore */
        Assert(TransactionIdFollowsOrEquals(xid, TransactionXmin));
 
+       /*
+        * Before going to the subtrans log, check our single item cache to see if
+        * we know the result from a previous/recent request.
+        */
+       if (TransactionIdEquals(xid, cachedFetchSubXid))
+               return cachedFetchTopmostXid;
+
        while (TransactionIdIsValid(parentXid))
        {
                previousXid = parentXid;
@@ -174,6 +189,9 @@ SubTransGetTopmostTransaction(TransactionId xid)
 
        Assert(TransactionIdIsValid(previousXid));
 
+       cachedFetchSubXid = xid;
+       cachedFetchTopmostXid = previousXid;
+
        return previousXid;
 }