Optimize SearchPathCache by saving the last entry.

Repeated lookups are common, so it's worth it to check the last entry
before doing another hash lookup.

Discussion: https://postgr.es/m/04c8592dbd694e4114a3ed87139a7a04e4363030.camel%40j-davis.com
This commit is contained in:
Jeff Davis 2023-12-04 17:19:16 -08:00
parent b14b1eb4da
commit a86c61c9ee

View File

@ -241,7 +241,8 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
* *
* The search path cache is based on a wrapper around a simplehash hash table * The search path cache is based on a wrapper around a simplehash hash table
* (nsphash, defined below). The spcache wrapper deals with OOM while trying * (nsphash, defined below). The spcache wrapper deals with OOM while trying
* to initialize a key, and also offers a more convenient API. * to initialize a key, optimizes repeated lookups of the same key, and also
* offers a more convenient API.
*/ */
static inline uint32 static inline uint32
@ -281,6 +282,7 @@ spcachekey_equal(SearchPathCacheKey a, SearchPathCacheKey b)
#define SPCACHE_RESET_THRESHOLD 256 #define SPCACHE_RESET_THRESHOLD 256
static nsphash_hash * SearchPathCache = NULL; static nsphash_hash * SearchPathCache = NULL;
static SearchPathCacheEntry * LastSearchPathCacheEntry = NULL;
/* /*
* Create or reset search_path cache as necessary. * Create or reset search_path cache as necessary.
@ -295,6 +297,7 @@ spcache_init(void)
return; return;
MemoryContextReset(SearchPathCacheContext); MemoryContextReset(SearchPathCacheContext);
LastSearchPathCacheEntry = NULL;
/* arbitrary initial starting size of 16 elements */ /* arbitrary initial starting size of 16 elements */
SearchPathCache = nsphash_create(SearchPathCacheContext, 16, NULL); SearchPathCache = nsphash_create(SearchPathCacheContext, 16, NULL);
searchPathCacheValid = true; searchPathCacheValid = true;
@ -307,12 +310,25 @@ spcache_init(void)
static SearchPathCacheEntry * static SearchPathCacheEntry *
spcache_lookup(const char *searchPath, Oid roleid) spcache_lookup(const char *searchPath, Oid roleid)
{ {
SearchPathCacheKey cachekey = { if (LastSearchPathCacheEntry &&
.searchPath = searchPath, LastSearchPathCacheEntry->key.roleid == roleid &&
.roleid = roleid strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
}; {
return LastSearchPathCacheEntry;
}
else
{
SearchPathCacheEntry *entry;
SearchPathCacheKey cachekey = {
.searchPath = searchPath,
.roleid = roleid
};
return nsphash_lookup(SearchPathCache, cachekey); entry = nsphash_lookup(SearchPathCache, cachekey);
LastSearchPathCacheEntry = entry;
return entry;
}
} }
/* /*
@ -324,35 +340,45 @@ spcache_lookup(const char *searchPath, Oid roleid)
static SearchPathCacheEntry * static SearchPathCacheEntry *
spcache_insert(const char *searchPath, Oid roleid) spcache_insert(const char *searchPath, Oid roleid)
{ {
SearchPathCacheEntry *entry; if (LastSearchPathCacheEntry &&
SearchPathCacheKey cachekey = { LastSearchPathCacheEntry->key.roleid == roleid &&
.searchPath = searchPath, strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
.roleid = roleid
};
/*
* searchPath is not saved in SearchPathCacheContext. First perform a
* lookup, and copy searchPath only if we need to create a new entry.
*/
entry = nsphash_lookup(SearchPathCache, cachekey);
if (!entry)
{ {
bool found; return LastSearchPathCacheEntry;
cachekey.searchPath = MemoryContextStrdup(SearchPathCacheContext, searchPath);
entry = nsphash_insert(SearchPathCache, cachekey, &found);
Assert(!found);
entry->oidlist = NIL;
entry->finalPath = NIL;
entry->firstNS = InvalidOid;
entry->temp_missing = false;
entry->forceRecompute = false;
/* do not touch entry->status, used by simplehash */
} }
else
{
SearchPathCacheEntry *entry;
SearchPathCacheKey cachekey = {
.searchPath = searchPath,
.roleid = roleid
};
return entry; /*
* searchPath is not saved in SearchPathCacheContext. First perform a
* lookup, and copy searchPath only if we need to create a new entry.
*/
entry = nsphash_lookup(SearchPathCache, cachekey);
if (!entry)
{
bool found;
cachekey.searchPath = MemoryContextStrdup(SearchPathCacheContext, searchPath);
entry = nsphash_insert(SearchPathCache, cachekey, &found);
Assert(!found);
entry->oidlist = NIL;
entry->finalPath = NIL;
entry->firstNS = InvalidOid;
entry->temp_missing = false;
entry->forceRecompute = false;
/* do not touch entry->status, used by simplehash */
}
LastSearchPathCacheEntry = entry;
return entry;
}
} }
/* /*