From c584f4434576742dce3afc699bb5264773d067b1 Mon Sep 17 00:00:00 2001 From: John Naylor Date: Thu, 19 Aug 2021 18:43:18 -0400 Subject: [PATCH v1] Specialize SearchSysCache4 by the search key data types Use a modified version of SearchCatCacheInternal as a template for specializing the search functions. The reason to do this is to avoid calling equality and hash functions via through a pointer, in the hopes this will improve syscache performance. --- src/backend/access/brin/brin_inclusion.c | 2 +- src/backend/access/brin/brin_minmax.c | 2 +- src/backend/access/brin/brin_minmax_multi.c | 2 +- src/backend/catalog/namespace.c | 2 +- src/backend/catalog/objectaddress.c | 4 +- src/backend/catalog/pg_operator.c | 2 +- src/backend/utils/cache/catcache.c | 55 +++++- src/backend/utils/cache/lsyscache.c | 4 +- src/backend/utils/cache/syscache.c | 29 ++- src/include/utils/catcache.h | 4 +- src/include/utils/catcache_search_template.h | 176 +++++++++++++++++++ src/include/utils/syscache.h | 6 +- 12 files changed, 266 insertions(+), 22 deletions(-) create mode 100644 src/include/utils/catcache_search_template.h diff --git a/src/backend/access/brin/brin_inclusion.c b/src/backend/access/brin/brin_inclusion.c index 0b384c0bd1..78e546821d 100644 --- a/src/backend/access/brin/brin_inclusion.c +++ b/src/backend/access/brin/brin_inclusion.c @@ -634,7 +634,7 @@ inclusion_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, opfamily = bdesc->bd_index->rd_opfamily[attno - 1]; attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); - tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily), + tuple = SearchSysCacheAMOPSTRATEGY(ObjectIdGetDatum(opfamily), ObjectIdGetDatum(attr->atttypid), ObjectIdGetDatum(subtype), Int16GetDatum(strategynum)); diff --git a/src/backend/access/brin/brin_minmax.c b/src/backend/access/brin/brin_minmax.c index 798f06c722..9d548f0576 100644 --- a/src/backend/access/brin/brin_minmax.c +++ b/src/backend/access/brin/brin_minmax.c @@ -294,7 +294,7 @@ minmax_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, opfamily = bdesc->bd_index->rd_opfamily[attno - 1]; attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); - tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily), + tuple = SearchSysCacheAMOPSTRATEGY(ObjectIdGetDatum(opfamily), ObjectIdGetDatum(attr->atttypid), ObjectIdGetDatum(subtype), Int16GetDatum(strategynum)); diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c index e3c98c2ffd..2ab4fb046a 100644 --- a/src/backend/access/brin/brin_minmax_multi.c +++ b/src/backend/access/brin/brin_minmax_multi.c @@ -2932,7 +2932,7 @@ minmax_multi_get_strategy_procinfo(BrinDesc *bdesc, uint16 attno, Oid subtype, opfamily = bdesc->bd_index->rd_opfamily[attno - 1]; attr = TupleDescAttr(bdesc->bd_tupdesc, attno - 1); - tuple = SearchSysCache4(AMOPSTRATEGY, ObjectIdGetDatum(opfamily), + tuple = SearchSysCacheAMOPSTRATEGY(ObjectIdGetDatum(opfamily), ObjectIdGetDatum(attr->atttypid), ObjectIdGetDatum(subtype), Int16GetDatum(strategynum)); diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index fd767fc5cf..5c700d537b 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -1545,7 +1545,7 @@ OpernameGetOprid(List *names, Oid oprleft, Oid oprright) { HeapTuple opertup; - opertup = SearchSysCache4(OPERNAMENSP, + opertup = SearchSysCacheOPERNAMENSP( CStringGetDatum(opername), ObjectIdGetDatum(oprleft), ObjectIdGetDatum(oprright), diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 9882e549c4..5aca2badb3 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -1751,7 +1751,7 @@ get_object_address_opf_member(ObjectType objtype, ObjectAddressSet(address, AccessMethodOperatorRelationId, InvalidOid); - tp = SearchSysCache4(AMOPSTRATEGY, + tp = SearchSysCacheAMOPSTRATEGY( ObjectIdGetDatum(famaddr.objectId), ObjectIdGetDatum(typeoids[0]), ObjectIdGetDatum(typeoids[1]), @@ -1782,7 +1782,7 @@ get_object_address_opf_member(ObjectType objtype, ObjectAddressSet(address, AccessMethodProcedureRelationId, InvalidOid); - tp = SearchSysCache4(AMPROCNUM, + tp = SearchSysCacheAMPROCNUM( ObjectIdGetDatum(famaddr.objectId), ObjectIdGetDatum(typeoids[0]), ObjectIdGetDatum(typeoids[1]), diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 6c270f9338..0dca12010b 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -136,7 +136,7 @@ OperatorGet(const char *operatorName, HeapTuple tup; Oid operatorObjectId; - tup = SearchSysCache4(OPERNAMENSP, + tup = SearchSysCacheOPERNAMENSP( PointerGetDatum(operatorName), ObjectIdGetDatum(leftObjectId), ObjectIdGetDatum(rightObjectId), diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 4fbdc62d8c..cd98766d59 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -1186,12 +1186,55 @@ SearchCatCache3(CatCache *cache, } -HeapTuple -SearchCatCache4(CatCache *cache, - Datum v1, Datum v2, Datum v3, Datum v4) -{ - return SearchCatCacheInternal(cache, 4, v1, v2, v3, v4); -} +/* 4-key search functions */ + +#define CC_SEARCH SearchCatCacheOidOidOidInt16 +#define CC_NKEYS 4 +#define FASTEQFUNC1 int4eqfast +#define FASTEQFUNC2 int4eqfast +#define FASTEQFUNC3 int4eqfast +#define FASTEQFUNC4 int2eqfast +#define HASHFUNC1 int4hashfast +#define HASHFUNC2 int4hashfast +#define HASHFUNC3 int4hashfast +#define HASHFUNC4 int2hashfast + +#include "utils/catcache_search_template.h" + +#undef CC_SEARCH +#undef CC_NKEYS +#undef FASTEQFUNC1 +#undef FASTEQFUNC2 +#undef FASTEQFUNC3 +#undef FASTEQFUNC4 +#undef HASHFUNC1 +#undef HASHFUNC2 +#undef HASHFUNC3 +#undef HASHFUNC4 + +#define CC_SEARCH SearchCatCacheNameOidOidOid +#define CC_NKEYS 4 +#define FASTEQFUNC1 nameeqfast +#define FASTEQFUNC2 int4eqfast +#define FASTEQFUNC3 int4eqfast +#define FASTEQFUNC4 int4eqfast +#define HASHFUNC1 namehashfast +#define HASHFUNC2 int4hashfast +#define HASHFUNC3 int4hashfast +#define HASHFUNC4 int4hashfast + +#include "utils/catcache_search_template.h" + +#undef CC_SEARCH +#undef CC_NKEYS +#undef FASTEQFUNC1 +#undef FASTEQFUNC2 +#undef FASTEQFUNC3 +#undef FASTEQFUNC4 +#undef HASHFUNC1 +#undef HASHFUNC2 +#undef HASHFUNC3 +#undef HASHFUNC4 /* * Work-horse for SearchCatCache/SearchCatCacheN. diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 4ebaa552a2..b5d7dcf94b 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -168,7 +168,7 @@ get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, Form_pg_amop amop_tup; Oid result; - tp = SearchSysCache4(AMOPSTRATEGY, + tp = SearchSysCacheAMOPSTRATEGY( ObjectIdGetDatum(opfamily), ObjectIdGetDatum(lefttype), ObjectIdGetDatum(righttype), @@ -797,7 +797,7 @@ get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum) Form_pg_amproc amproc_tup; RegProcedure result; - tp = SearchSysCache4(AMPROCNUM, + tp = SearchSysCacheAMPROCNUM( ObjectIdGetDatum(opfamily), ObjectIdGetDatum(lefttype), ObjectIdGetDatum(righttype), diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index d6cb78dea8..b0131374ea 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -1157,14 +1157,33 @@ SearchSysCache3(int cacheId, } HeapTuple -SearchSysCache4(int cacheId, +SearchSysCacheAMOPSTRATEGY( Datum key1, Datum key2, Datum key3, Datum key4) { - Assert(cacheId >= 0 && cacheId < SysCacheSize && - PointerIsValid(SysCache[cacheId])); - Assert(SysCache[cacheId]->cc_nkeys == 4); + Assert(PointerIsValid(SysCache[AMOPSTRATEGY])); + Assert(SysCache[AMOPSTRATEGY]->cc_nkeys == 4); + + return SearchCatCacheOidOidOidInt16(SysCache[AMOPSTRATEGY], key1, key2, key3, key4); +} + +HeapTuple +SearchSysCacheAMPROCNUM( + Datum key1, Datum key2, Datum key3, Datum key4) +{ + Assert(PointerIsValid(SysCache[AMPROCNUM])); + Assert(SysCache[AMPROCNUM]->cc_nkeys == 4); + + return SearchCatCacheOidOidOidInt16(SysCache[AMPROCNUM], key1, key2, key3, key4); +} + +HeapTuple +SearchSysCacheOPERNAMENSP( + Datum key1, Datum key2, Datum key3, Datum key4) +{ + Assert(PointerIsValid(SysCache[OPERNAMENSP])); + Assert(SysCache[OPERNAMENSP]->cc_nkeys == 4); - return SearchCatCache4(SysCache[cacheId], key1, key2, key3, key4); + return SearchCatCacheNameOidOidOid(SysCache[OPERNAMENSP], key1, key2, key3, key4); } /* diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h index ddc2762eb3..623133f57b 100644 --- a/src/include/utils/catcache.h +++ b/src/include/utils/catcache.h @@ -204,7 +204,9 @@ extern HeapTuple SearchCatCache2(CatCache *cache, Datum v1, Datum v2); extern HeapTuple SearchCatCache3(CatCache *cache, Datum v1, Datum v2, Datum v3); -extern HeapTuple SearchCatCache4(CatCache *cache, +extern HeapTuple SearchCatCacheOidOidOidInt16(CatCache *cache, + Datum v1, Datum v2, Datum v3, Datum v4); +extern HeapTuple SearchCatCacheNameOidOidOid(CatCache *cache, Datum v1, Datum v2, Datum v3, Datum v4); extern void ReleaseCatCache(HeapTuple tuple); diff --git a/src/include/utils/catcache_search_template.h b/src/include/utils/catcache_search_template.h new file mode 100644 index 0000000000..6f5dc2573c --- /dev/null +++ b/src/include/utils/catcache_search_template.h @@ -0,0 +1,176 @@ +/*------------------------------------------------------------------------- + * catcache_search_template.h + * + * A template for type-specialized SearchCatCache functions + * + * Usage notes: + * + * To generate functions specialized for a set of catcache keys, + * the following parameter macros should be #define'd before this + * file is included. + * + * - CC_SEARCH - the name of the search function to be generated + * - CC_NKEYS - the number of search keys for the tuple + * - FASTEQFUNCx (x in 1,2,3,4) - type-specific equality function(s) + * - HASHFUNCx (x in 1,2,3,4) - type-specific hash function(s) + * + * + * Copyright (c) 2021, PostgreSQL Global Development Group + * Portions Copyright (c) 1992-1994, Regents of the University of California + * + * src/include/utils/catcache_search_template.h + * + *------------------------------------------------------------------------- + */ + + +HeapTuple +CC_SEARCH(CatCache *cache, + Datum v1, + Datum v2, + Datum v3, + Datum v4) +{ + uint32 hashValue = 0; + uint32 oneHash; + Index hashIndex; + dlist_iter iter; + dlist_head *bucket; + CatCTup *ct; + + /* Make sure we're in an xact, even if this ends up being a cache hit */ + Assert(IsTransactionState()); + + Assert(cache->cc_nkeys == CC_NKEYS); + + /* + * one-time startup overhead for each cache + */ + if (unlikely(cache->cc_tupdesc == NULL)) + CatalogCacheInitializeCache(cache); + +#ifdef CATCACHE_STATS + cache->cc_searches++; +#endif + + /* + * find the hash bucket in which to look for the tuple + */ + CACHE_elog(DEBUG2, "CatalogCacheComputeHashValue %s %d %p", + cache->cc_relname, CC_NKEYS, cache); + + switch (CC_NKEYS) + { + case 4: + oneHash = HASHFUNC4(v4); + + hashValue ^= oneHash << 24; + hashValue ^= oneHash >> 8; + /* FALLTHROUGH */ + case 3: + oneHash = HASHFUNC3(v3); + + hashValue ^= oneHash << 16; + hashValue ^= oneHash >> 16; + /* FALLTHROUGH */ + case 2: + oneHash = HASHFUNC2(v2); + + hashValue ^= oneHash << 8; + hashValue ^= oneHash >> 24; + /* FALLTHROUGH */ + case 1: + oneHash = HASHFUNC1(v1); + + hashValue ^= oneHash; + break; + default: + elog(FATAL, "wrong number of hash keys: %d", CC_NKEYS); + break; + } + + hashIndex = HASH_INDEX(hashValue, cache->cc_nbuckets); + + /* + * scan the hash bucket until we find a match or exhaust our tuples + * + * Note: it's okay to use dlist_foreach here, even though we modify the + * dlist within the loop, because we don't continue the loop afterwards. + */ + bucket = &cache->cc_bucket[hashIndex]; + dlist_foreach(iter, bucket) + { + ct = dlist_container(CatCTup, cache_elem, iter.cur); + + if (ct->dead) + continue; /* ignore dead entries */ + + if (ct->hash_value != hashValue) + continue; /* quickly skip entry if wrong hash val */ + + switch (CC_NKEYS) + { + case 4: + if (!FASTEQFUNC4(ct->keys[3], v4)) + continue; + /* FALLTHROUGH */ + case 3: + if (!FASTEQFUNC3(ct->keys[2], v3)) + continue; + /* FALLTHROUGH */ + case 2: + if (!FASTEQFUNC2(ct->keys[1], v2)) + continue; + /* FALLTHROUGH */ + case 1: + if (!FASTEQFUNC1(ct->keys[0], v1)) + continue; + break; + default: + elog(FATAL, "wrong number of keys: %d", CC_NKEYS); + break; + } + + /* + * We found a match in the cache. Move it to the front of the list + * for its hashbucket, in order to speed subsequent searches. (The + * most frequently accessed elements in any hashbucket will tend to be + * near the front of the hashbucket's list.) + */ + dlist_move_head(bucket, &ct->cache_elem); + + /* + * If it's a positive entry, bump its refcount and return it. If it's + * negative, we can report failure to the caller. + */ + if (!ct->negative) + { + ResourceOwnerEnlargeCatCacheRefs(CurrentResourceOwner); + ct->refcount++; + ResourceOwnerRememberCatCacheRef(CurrentResourceOwner, &ct->tuple); + + CACHE_elog(DEBUG2, "SearchCatCache(%s): found in bucket %d", + cache->cc_relname, hashIndex); + +#ifdef CATCACHE_STATS + cache->cc_hits++; +#endif + + return &ct->tuple; + } + else + { + CACHE_elog(DEBUG2, "SearchCatCache(%s): found neg entry in bucket %d", + cache->cc_relname, hashIndex); + +#ifdef CATCACHE_STATS + cache->cc_neg_hits++; +#endif + + return NULL; + } + } + + return SearchCatCacheMiss(cache, CC_NKEYS, hashValue, hashIndex, v1, v2, v3, v4); +} + diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index d74a348600..5396f9ccfd 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -130,7 +130,11 @@ extern HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2); extern HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3); -extern HeapTuple SearchSysCache4(int cacheId, +extern HeapTuple SearchSysCacheAMOPSTRATEGY( + Datum key1, Datum key2, Datum key3, Datum key4); +extern HeapTuple SearchSysCacheAMPROCNUM( + Datum key1, Datum key2, Datum key3, Datum key4); +extern HeapTuple SearchSysCacheOPERNAMENSP( Datum key1, Datum key2, Datum key3, Datum key4); extern void ReleaseSysCache(HeapTuple tuple); -- 2.31.1