Optimize memory access in GetRunningTransactionData()
authorAlexander Korotkov <akorotkov@postgresql.org>
Wed, 3 Jul 2024 23:05:37 +0000 (02:05 +0300)
committerAlexander Korotkov <akorotkov@postgresql.org>
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;