From 73058e520cce39a598a1011ec05f84b4f7ee8d97 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Wed, 22 Jan 2020 18:00:38 -0800 Subject: [PATCH v2 1/3] 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 c573814f01..7e4cd9c5ad 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -560,6 +560,7 @@ _bt_compare(Relation rel, BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page); IndexTuple itup; ItemPointer heapTid; + int ski; ScanKey scankey; int ncmpkey; int ntupatts; @@ -591,9 +592,11 @@ _bt_compare(Relation rel, */ ncmpkey = Min(ntupatts, key->keysz); + Assert(ntupatts >= 1); Assert(key->heapkeyspace || ncmpkey == key->keysz); + ski = 1; scankey = key->scankeys; - for (int i = 1; i <= ncmpkey; i++) + for (;;) { Datum datum; bool isNull; @@ -641,7 +644,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