From 703ddd56fb484692c84101d1731e60f9ea81193f Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Wed, 13 Sep 2017 19:43:02 -0700 Subject: [PATCH 5/8] Replace binary search in fmgr_isbuiltin with hashtable. Turns out we have enough functions that the binary search is quite noticeable in profiles. It'd be nice if there were a better place to build the hashtable than the first pass through fmgr_isbuiltin() but there's currently none. --- src/backend/utils/fmgr/fmgr.c | 63 ++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index a7b07827e0..87867f2183 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -26,6 +26,7 @@ #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgrtab.h" +#include "utils/hashutils.h" #include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -36,6 +37,30 @@ PGDLLIMPORT needs_fmgr_hook_type needs_fmgr_hook = NULL; PGDLLIMPORT fmgr_hook_type fmgr_hook = NULL; +/* + * Hashtable for fast lookup builtin functions. + */ +typedef struct BuiltinOidLookupEntry +{ + Oid foid; + int status; + const FmgrBuiltin *builtin; +} BuiltinOidLookupEntry; + +/* define hashtable mapping block numbers to PagetableEntry's */ +#define SH_PREFIX oid2builtins +#define SH_ELEMENT_TYPE BuiltinOidLookupEntry +#define SH_KEY_TYPE Oid +#define SH_KEY foid +#define SH_HASH_KEY(tb, key) murmurhash32(key) +#define SH_EQUAL(tb, a, b) a == b +#define SH_SCOPE static inline +#define SH_DEFINE +#define SH_DECLARE +#include "lib/simplehash.h" + +static oid2builtins_hash *oid2builtins = 0; + /* * Hashtable for fast lookup of external C functions */ @@ -70,26 +95,32 @@ static Datum fmgr_security_definer(PG_FUNCTION_ARGS); static const FmgrBuiltin * fmgr_isbuiltin(Oid id) { - int low = 0; - int high = fmgr_nbuiltins - 1; + BuiltinOidLookupEntry *entry; - /* - * Loop invariant: low is the first index that could contain target entry, - * and high is the last index that could contain it. - */ - while (low <= high) + /* TODO: it'd be better if this were done separately */ + if (unlikely(oid2builtins == NULL)) { - int i = (high + low) / 2; - const FmgrBuiltin *ptr = &fmgr_builtins[i]; + int i; - if (id == ptr->foid) - return ptr; - else if (id > ptr->foid) - low = i + 1; - else - high = i - 1; + oid2builtins = oid2builtins_create(TopMemoryContext, + fmgr_nbuiltins, + NULL); + for (i = 0; i < fmgr_nbuiltins; i++) + { + const FmgrBuiltin *ptr = &fmgr_builtins[i]; + bool found; + + entry = oid2builtins_insert(oid2builtins, ptr->foid, &found); + Assert(!found); + entry->builtin = ptr; + } } - return NULL; + + entry = oid2builtins_lookup(oid2builtins, id); + if (entry) + return entry->builtin; + else + return NULL; } /* -- 2.14.1.536.g6867272d5b.dirty