Optimize memory access in GetRunningTransactionData()
authorAlexander Korotkov <[email protected]>
Wed, 3 Jul 2024 23:05:37 +0000 (02:05 +0300)
committerAlexander Korotkov <[email protected]>
Wed, 3 Jul 2024 23:05:37 +0000 (02:05 +0300)
e85662df44 made GetRunningTransactionData() calculate the oldest running
transaction id within the current database.  This commit optimized this
calculation by performing a cheap transaction id comparison before fetching
the process database id, while the latter could cause extra cache misses.

Reported-by: Noah Misch
Discussion: https://postgr.es/m/20240630231816.bf.nmisch%40google.com

src/backend/storage/ipc/procarray.c

index 9fc930e98f845c461cebc3ceb6eb05456b89ac7f..16b5803d388fadb2fec44643733bd794e35f3786 100644 (file)
@@ -2753,8 +2753,6 @@ GetRunningTransactionData(void)
     */
    for (index = 0; index < arrayP->numProcs; index++)
    {
-       int         pgprocno = arrayP->pgprocnos[index];
-       PGPROC     *proc = &allProcs[pgprocno];
        TransactionId xid;
 
        /* Fetch xid just once - see GetNewTransactionId */
@@ -2776,11 +2774,18 @@ GetRunningTransactionData(void)
            oldestRunningXid = xid;
 
        /*
-        * Also, update the oldest running xid within the current database.
+        * Also, update the oldest running xid within the current database. As
+        * fetching pgprocno and PGPROC could cause cache misses, we do cheap
+        * TransactionId comparison first.
         */
-       if (proc->databaseId == MyDatabaseId &&
-           TransactionIdPrecedes(xid, oldestDatabaseRunningXid))
-           oldestDatabaseRunningXid = xid;
+       if (TransactionIdPrecedes(xid, oldestDatabaseRunningXid))
+       {
+           int         pgprocno = arrayP->pgprocnos[index];
+           PGPROC     *proc = &allProcs[pgprocno];
+
+           if (proc->databaseId == MyDatabaseId)
+               oldestDatabaseRunningXid = xid;
+       }
 
        if (ProcGlobal->subxidStates[index].overflowed)
            suboverflowed = true;