From 01b053b473d897c71725a7bb09a3127fc78140dc Mon Sep 17 00:00:00 2001 From: John Naylor Date: Wed, 22 Nov 2023 18:45:48 +0700 Subject: [PATCH v4 3/3] Optimize GUC functions for simple hash Only downcase a character when an equality check fails, since we expect most names to be lower case. Also simplify downcasing in the hash function. --- src/backend/utils/misc/guc.c | 40 ++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index bf05b022c3..7896deb63b 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -229,6 +229,7 @@ static int GUCNestLevel = 0; /* 1 when in main transaction */ static int guc_var_compare(const void *a, const void *b); +static bool guc_name_eq(const char *namea, const char *nameb); static uint32 guc_name_hash(const char *name); static void InitializeGUCOptionsFromEnvironment(void); static void InitializeOneGUCOption(struct config_generic *gconf); @@ -271,7 +272,7 @@ static bool call_enum_check_hook(struct config_enum *conf, int *newval, #define SH_KEY_TYPE const char * #define SH_KEY gucname #define SH_HASH_KEY(tb, key) guc_name_hash(key) -#define SH_EQUAL(tb, a, b) (guc_name_compare(a, b) == 0) +#define SH_EQUAL(tb, a, b) (guc_name_eq(a, b)) #define SH_SCOPE static inline #define SH_DECLARE #define SH_DEFINE @@ -1308,6 +1309,38 @@ guc_name_compare(const char *namea, const char *nameb) return 0; } +static bool +guc_name_eq(const char *namea, const char *nameb) +{ + char cha; + char chb; + + while (*namea && *nameb) + { + cha = *namea++; + chb = *nameb++; + + if (cha != chb) + { + /* Casefold lazily since we expect lower case */ + if (cha >= 'A' && cha <= 'Z') + cha += 'a' - 'A'; + if (chb >= 'A' && chb <= 'Z') + chb += 'a' - 'A'; + + if (cha != chb) + return false; + } + } + + if (*namea == *nameb) + return true; + else + return false; + + //Assert(guc_name_compare(namea, nameb) == 0); +} + /* * Hash function that's compatible with guc_name_compare */ @@ -1320,9 +1353,8 @@ guc_name_hash(const char *name) { char ch = *name++; - /* Case-fold in the same way as guc_name_compare */ - if (ch >= 'A' && ch <= 'Z') - ch += 'a' - 'A'; + /* quick and dirty casefolding suitable for hashing */ + ch |= 0x20; /* Merge into hash ... not very bright, but it needn't be */ result = pg_rotate_left32(result, 5); -- 2.42.0