v7-0005-Optimize-SearchPathCache-by-saving-the-last-entry.patch
text/x-patch
Filename: v7-0005-Optimize-SearchPathCache-by-saving-the-last-entry.patch
Type: text/x-patch
Part: 2
Message:
Re: Faster "SET search_path"
Patch
Format: format-patch
Series: patch v7-0005
Subject: Optimize SearchPathCache by saving the last entry.
| File | + | − |
|---|---|---|
| src/backend/catalog/namespace.c | 67 | 40 |
From 8b5e905cbffa9eadd1e0d4fa6af7e7b77a93b7c7 Mon Sep 17 00:00:00 2001
From: Jeff Davis <jeff@j-davis.com>
Date: Thu, 19 Oct 2023 15:48:16 -0700
Subject: [PATCH v7 5/6] 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
---
src/backend/catalog/namespace.c | 107 ++++++++++++++++++++------------
1 file changed, 67 insertions(+), 40 deletions(-)
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 68deb86554..ff7169dc99 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -240,7 +240,8 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames,
*
* 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
- * 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
@@ -280,6 +281,7 @@ spcachekey_equal(SearchPathCacheKey a, SearchPathCacheKey b)
#define SPCACHE_RESET_THRESHOLD 1024
static nsphash_hash *SearchPathCache = NULL;
+static SearchPathCacheEntry *LastSearchPathCacheEntry = NULL;
/*
* Create search path cache.
@@ -308,6 +310,7 @@ spcache_reset(void)
MemoryContextReset(SearchPathCacheContext);
SearchPathCache = NULL;
+ LastSearchPathCacheEntry = NULL;
spcache_init();
}
@@ -325,12 +328,25 @@ spcache_members(void)
static SearchPathCacheEntry *
spcache_lookup(const char *searchPath, Oid roleid)
{
- SearchPathCacheKey cachekey = {
- .searchPath = searchPath,
- .roleid = roleid
- };
+ if (LastSearchPathCacheEntry &&
+ LastSearchPathCacheEntry->key.roleid == roleid &&
+ strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
+ {
+ return LastSearchPathCacheEntry;
+ }
+ else
+ {
+ SearchPathCacheEntry *entry;
+ SearchPathCacheKey cachekey = {
+ .searchPath = searchPath,
+ .roleid = roleid
+ };
+
+ entry = nsphash_lookup(SearchPathCache, cachekey);
- return nsphash_lookup(SearchPathCache, cachekey);
+ LastSearchPathCacheEntry = entry;
+ return entry;
+ }
}
/*
@@ -342,48 +358,59 @@ spcache_lookup(const char *searchPath, Oid roleid)
static SearchPathCacheEntry *
spcache_insert(const char *searchPath, Oid roleid)
{
- SearchPathCacheEntry *entry;
- bool found;
- SearchPathCacheKey cachekey = {
- .searchPath = searchPath,
- .roleid = roleid
- };
+ if (LastSearchPathCacheEntry &&
+ LastSearchPathCacheEntry->key.roleid == roleid &&
+ strcmp(LastSearchPathCacheEntry->key.searchPath, searchPath) == 0)
+ {
+ return LastSearchPathCacheEntry;
+ }
+ else
+ {
+ SearchPathCacheEntry *entry;
+ bool found;
+ SearchPathCacheKey cachekey = {
+ .searchPath = searchPath,
+ .roleid = roleid
+ };
- entry = nsphash_insert(SearchPathCache, cachekey, &found);
+ entry = nsphash_insert(SearchPathCache, cachekey, &found);
- /* ensure that key is initialized and the rest is zeroed */
- if (!found)
- {
- size_t size = strlen(searchPath) + 1;
- char *newstr;
+ /* ensure that key is initialized and the rest is zeroed */
+ if (!found)
+ {
+ size_t size = strlen(searchPath) + 1;
+ char *newstr;
- /* do not touch entry->status, used by simplehash */
- entry->oidlist = NIL;
- entry->finalPath = NIL;
- entry->firstNS = InvalidOid;
- entry->temp_missing = false;
+ /* do not touch entry->status, used by simplehash */
+ entry->oidlist = NIL;
+ entry->finalPath = NIL;
+ entry->firstNS = InvalidOid;
+ entry->temp_missing = false;
- newstr = MemoryContextAllocExtended(SearchPathCacheContext, size,
- MCXT_ALLOC_NO_OOM);
+ newstr = MemoryContextAllocExtended(SearchPathCacheContext, size,
+ MCXT_ALLOC_NO_OOM);
- /* if we can't initialize the key due to OOM, delete the entry */
- if (newstr == NULL)
- {
- nsphash_delete_item(SearchPathCache, entry);
- MemoryContextStats(TopMemoryContext);
- ereport(ERROR,
- (errcode(ERRCODE_OUT_OF_MEMORY),
- errmsg("out of memory"),
- errdetail("Failed on request of size %zu in memory context \"%s\".",
- size, SearchPathCacheContext->name)));
+ /* if we can't initialize the key due to OOM, delete the entry */
+ if (newstr == NULL)
+ {
+ nsphash_delete_item(SearchPathCache, entry);
+ MemoryContextStats(TopMemoryContext);
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory"),
+ errdetail("Failed on request of size %zu in memory context \"%s\".",
+ size, SearchPathCacheContext->name)));
+
+ }
+
+ memcpy(newstr, searchPath, size);
+ entry->key.searchPath = newstr;
+ entry->key.roleid = roleid;
}
- memcpy(newstr, searchPath, size);
- entry->key.searchPath = newstr;
- entry->key.roleid = roleid;
+ LastSearchPathCacheEntry = entry;
+ return entry;
}
-
- return entry;
}
/*
--
2.34.1