From 82252e4abdceb2716d4bb3a89634570e826b50a3 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Wed, 22 Jan 2020 18:00:38 -0800 Subject: [PATCH v5 1/2] Avoid pipeline stall in _bt_compare(). Author: Peter Geoghegan Reviewed-By: Andres Freund, Floris Van Nee Discussion: https://postgr.es/m/CAH2-Wzngz5MrkiTaZNny0GzfTxNQE+QWPPaO-C390BgruhgjEw@mail.gmail.com --- src/backend/access/nbtree/nbtsearch.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 7aaa8c17b0..98642cbccb 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -655,6 +655,7 @@ _bt_compare(Relation rel, BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page); IndexTuple itup; ItemPointer heapTid; + int ski; ScanKey scankey; int ncmpkey; int ntupatts; @@ -687,10 +688,12 @@ _bt_compare(Relation rel, */ ncmpkey = Min(ntupatts, key->keysz); + Assert(ntupatts >= 1); Assert(key->heapkeyspace || ncmpkey == key->keysz); Assert(!BTreeTupleIsPosting(itup) || key->allequalimage); + ski = 1; scankey = key->scankeys; - for (int i = 1; i <= ncmpkey; i++) + for (;;) { Datum datum; bool isNull; @@ -736,7 +739,18 @@ _bt_compare(Relation rel, if (result != 0) return result; + /* + * The loop is deliberately structured in a way that enables the + * compiler to assume that the first iteration always runs. Testing + * has shown that this avoids a pipeline stall with certain + * memory-bound workloads. We delay this test, since it depends on + * whether or not caller's tuple is a pivot tuple. Typically, most + * calls here never reach this far. + */ + ski++; scankey++; + if (ski > ncmpkey) + break; } /* -- 2.17.1