From c7bf0aaa470028372b27e05cf8b9132793ee18a8 Mon Sep 17 00:00:00 2001 From: Borodin Andrey Date: Sat, 24 Oct 2020 15:47:20 +0500 Subject: [PATCH] Make GiST deterministic This commit adds PRNG state of randomness used in GiST insertion to GiST state. This renders all test runs detrministic. --- src/backend/access/gist/gist.c | 7 +++++++ src/backend/access/gist/gistutil.c | 5 +++-- src/backend/utils/misc/guc.c | 11 +++++++++++ src/include/access/gist.h | 2 ++ src/include/access/gist_private.h | 3 +++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 25b42e38f2..0b5842068a 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -27,6 +27,8 @@ #include "utils/memutils.h" #include "utils/rel.h" +double gist_seed; + /* non-export function prototypes */ static void gistfixsplit(GISTInsertState *state, GISTSTATE *giststate); static bool gistinserttuple(GISTInsertState *state, GISTInsertStack *stack, @@ -1617,6 +1619,11 @@ initGISTstate(Relation index) giststate->supportCollation[i] = InvalidOid; } + memset(&giststate->random_state, 0, sizeof(giststate->random_state)); + memcpy(&giststate->random_state, + &gist_seed, + Min(sizeof(giststate->random_state), sizeof(gist_seed))); + MemoryContextSwitchTo(oldCxt); return giststate; diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c index 615b5ade23..2ca53068c4 100644 --- a/src/backend/access/gist/gistutil.c +++ b/src/backend/access/gist/gistutil.c @@ -19,6 +19,7 @@ #include "access/htup_details.h" #include "access/reloptions.h" #include "catalog/pg_opclass.h" +#include "port.h" #include "storage/indexfsm.h" #include "storage/lmgr.h" #include "utils/float.h" @@ -507,7 +508,7 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */ if (keep_current_best == -1) { /* we didn't make the random choice yet for this old best */ - keep_current_best = (random() <= (MAX_RANDOM_VALUE / 2)) ? 1 : 0; + keep_current_best = pg_jrand48(giststate->random_state) & 1; } if (keep_current_best == 0) { @@ -529,7 +530,7 @@ gistchoose(Relation r, Page p, IndexTuple it, /* it has compressed entry */ if (keep_current_best == -1) { /* we didn't make the random choice yet for this old best */ - keep_current_best = (random() <= (MAX_RANDOM_VALUE / 2)) ? 1 : 0; + keep_current_best = pg_jrand48(giststate->random_state) & 1; } if (keep_current_best == 1) break; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index a62d64eaa4..f2be4700e7 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -30,6 +30,7 @@ #include #include "access/commit_ts.h" +#include "access/gist.h" #include "access/gin.h" #include "access/rmgr.h" #include "access/tableam.h" @@ -3552,6 +3553,16 @@ static struct config_real ConfigureNamesReal[] = 0.0, 0.0, 1.0, NULL, NULL, NULL }, + { + {"gist_seed", PGC_USERSET, DEVELOPER_OPTIONS, + gettext_noop("Seed for random path selection in GiST insertion."), + NULL, + GUC_EXPLAIN + }, + &gist_seed, + 0.0, 0.0, 1.0, + NULL, NULL, NULL + }, { {"hash_mem_multiplier", PGC_USERSET, RESOURCES_MEM, diff --git a/src/include/access/gist.h b/src/include/access/gist.h index 4f6dae9a76..9fde15a399 100644 --- a/src/include/access/gist.h +++ b/src/include/access/gist.h @@ -237,4 +237,6 @@ typedef struct do { (e).key = (k); (e).rel = (r); (e).page = (pg); \ (e).offset = (o); (e).leafkey = (l); } while (0) +extern double gist_seed; + #endif /* GIST_H */ diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h index b68c01a5f2..07319a225e 100644 --- a/src/include/access/gist_private.h +++ b/src/include/access/gist_private.h @@ -95,6 +95,9 @@ typedef struct GISTSTATE /* Collations to pass to the support functions */ Oid supportCollation[INDEX_MAX_KEYS]; + + /* Random state for gistchoose tie breaker PRNG */ + unsigned short random_state[3]; } GISTSTATE; -- 2.24.3 (Apple Git-128)