summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Naylor2022-08-03 16:59:28 +0000
committerJohn Naylor2022-08-11 02:17:42 +0000
commit37a6e5df3713498a21942dae2ed3122bba5b9f50 (patch)
treebbcf0b95eb0a86aa9b49cf8ef23bbfcac6d0843f
parenta8c012869763c711abc9085f54b2a100b60a85fa (diff)
Optimize xid/subxid searches in XidInMVCCSnapshot().
As reported by Yura Sokolov, scanning the snapshot->xip array has noticeable impact on scalability when there are a large number of concurrent writers. Use the optimized (on x86-64) routine from b6ef16756 to speed up searches through the [sub]xip arrays. One benchmark showed a 5% increase in transaction throughput with 128 concurrent writers, and a 50% increase in a pathological case of 1024 writers. While a hash table would have scaled even better, it was ultimately rejected because of concerns around code complexity and memory allocation. Credit to Andres Freund for the idea to optimize linear search using SIMD instructions. Nathan Bossart Reviewed by: Andres Freund, John Naylor, Bharath Rupireddy, Masahiko Sawada Discussion: https://postgr.es/m/20220713170950.GA3116318%40nathanxps13
-rw-r--r--src/backend/utils/time/snapmgr.c28
1 files changed, 7 insertions, 21 deletions
diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c
index 5bc2a15160..9b504c9745 100644
--- a/src/backend/utils/time/snapmgr.c
+++ b/src/backend/utils/time/snapmgr.c
@@ -56,6 +56,7 @@
#include "datatype/timestamp.h"
#include "lib/pairingheap.h"
#include "miscadmin.h"
+#include "port/pg_lfind.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "storage/procarray.h"
@@ -2284,8 +2285,6 @@ RestoreTransactionSnapshot(Snapshot snapshot, void *source_pgproc)
bool
XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
{
- uint32 i;
-
/*
* Make a quick range check to eliminate most XIDs without looking at the
* xip arrays. Note that this is OK even if we convert a subxact XID to
@@ -2317,13 +2316,8 @@ XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
if (!snapshot->suboverflowed)
{
/* we have full data, so search subxip */
- int32 j;
-
- for (j = 0; j < snapshot->subxcnt; j++)
- {
- if (TransactionIdEquals(xid, snapshot->subxip[j]))
- return true;
- }
+ if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
+ return true;
/* not there, fall through to search xip[] */
}
@@ -2344,16 +2338,11 @@ XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
return false;
}
- for (i = 0; i < snapshot->xcnt; i++)
- {
- if (TransactionIdEquals(xid, snapshot->xip[i]))
- return true;
- }
+ if (pg_lfind32(xid, snapshot->xip, snapshot->xcnt))
+ return true;
}
else
{
- int32 j;
-
/*
* In recovery we store all xids in the subxact array because it is by
* far the bigger array, and we mostly don't know which xids are
@@ -2383,11 +2372,8 @@ XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
* indeterminate xid. We don't know whether it's top level or subxact
* but it doesn't matter. If it's present, the xid is visible.
*/
- for (j = 0; j < snapshot->subxcnt; j++)
- {
- if (TransactionIdEquals(xid, snapshot->subxip[j]))
- return true;
- }
+ if (pg_lfind32(xid, snapshot->subxip, snapshot->subxcnt))
+ return true;
}
return false;