From 6bee9c944230ab414c9f07871ffdf9ee6ee84ad6 Mon Sep 17 00:00:00 2001 From: "dgrowley@gmail.com" Date: Tue, 8 Dec 2020 17:54:04 +1300 Subject: [PATCH v14 4/4] Remove code duplication in nodeResultCache.c --- src/backend/executor/nodeResultCache.c | 123 ++++++++++--------------- 1 file changed, 51 insertions(+), 72 deletions(-) diff --git a/src/backend/executor/nodeResultCache.c b/src/backend/executor/nodeResultCache.c index 4ff8000003..4d6cd9ecfe 100644 --- a/src/backend/executor/nodeResultCache.c +++ b/src/backend/executor/nodeResultCache.c @@ -425,6 +425,54 @@ cache_reduce_memory(ResultCacheState *rcstate, ResultCacheKey *specialkey) return specialkey_intact; } +/* + * cache_check_mem + * Check if we've allocated more than our memory budget and, if so, + * reduce the memory used by the cache. Returns the cache entry + * belonging to 'entry', which may have changed address by shuffling the + * deleted entries back to their optimal position. Returns NULL if the + * attempt to free enough memory resulted in 'entry' itself being evicted + * from the cache. + */ +static ResultCacheEntry * +cache_check_mem(ResultCacheState *rcstate, ResultCacheEntry *entry) +{ + /* + * If we've gone over our memory budget, then we'll free up some space in + * the cache. + */ + if (rcstate->mem_used > rcstate->mem_limit) + { + ResultCacheKey *key = entry->key; + + if (!cache_reduce_memory(rcstate, key)) + return NULL; + + /* + * The process of removing entries from the cache may have caused the + * code in simplehash.h to shuffle elements to earlier buckets in the + * hash table. If it has, we'll need to find the entry again by + * performing a lookup. Fortunately, we can detect if this has + * happened by seeing if the entry is still in use and that the key + * pointer matches our expected key. + */ + if (entry->status != resultcache_SH_IN_USE || entry->key != key) + { + /* + * We need to repopulate the probeslot as lookups performed during + * the cache evictions above will have stored some other key. + */ + prepare_probe_slot(rcstate, key); + + /* Re-find the newly added entry */ + entry = resultcache_lookup(rcstate->hashtable, NULL); + Assert(entry != NULL); + } + } + + return entry; +} + /* * cache_lookup * Perform a lookup to see if we've already cached results based on the @@ -487,44 +535,7 @@ cache_lookup(ResultCacheState *rcstate, bool *found) MemoryContextSwitchTo(oldcontext); - /* - * If we've gone over our memory budget, then we'll free up some space in - * the cache. - */ - if (rcstate->mem_used > rcstate->mem_limit) - { - /* - * Try to free up some memory. It's highly unlikely that we'll fail - * to do so here since the entry we've just added is yet to contain - * any tuples and we're able to remove any other entry to reduce the - * memory consumption. - */ - if (unlikely(!cache_reduce_memory(rcstate, key))) - return NULL; - - /* - * The process of removing entries from the cache may have caused the - * code in simplehash.h to shuffle elements to earlier buckets in the - * hash table. If it has, we'll need to find the entry again by - * performing a lookup. Fortunately, we can detect if this has - * happened by seeing if the entry is still in use and that the key - * pointer matches our expected key. - */ - if (entry->status != resultcache_SH_IN_USE || entry->key != key) - { - /* - * We need to repopulate the probeslot as lookups performed during - * the cache evictions above will have stored some other key. - */ - prepare_probe_slot(rcstate, key); - - /* Re-find the newly added entry */ - entry = resultcache_lookup(rcstate->hashtable, NULL); - Assert(entry != NULL); - } - } - - return entry; + return cache_check_mem(rcstate, entry); } /* @@ -570,41 +581,9 @@ cache_store_tuple(ResultCacheState *rcstate, TupleTableSlot *slot) rcstate->last_tuple = tuple; MemoryContextSwitchTo(oldcontext); - /* - * If we've gone over our memory budget then free up some space in the - * cache. - */ - if (rcstate->mem_used > rcstate->mem_limit) - { - ResultCacheKey *key = entry->key; - - if (!cache_reduce_memory(rcstate, key)) - return false; - - /* - * The process of removing entries from the cache may have caused the - * code in simplehash.h to shuffle elements to earlier buckets in the - * hash table. If it has, we'll need to find the entry again by - * performing a lookup. Fortunately, we can detect if this has - * happened by seeing if the entry is still in use and that the key - * pointer matches our expected key. - */ - if (entry->status != resultcache_SH_IN_USE || entry->key != key) - { - /* - * We need to repopulate the probeslot as lookups performed during - * the cache evictions above will have stored some other key. - */ - prepare_probe_slot(rcstate, key); - - /* Re-find the entry */ - rcstate->entry = entry = resultcache_lookup(rcstate->hashtable, - NULL); - Assert(entry != NULL); - } - } + rcstate->entry = entry = cache_check_mem(rcstate, entry); - return true; + return (entry != NULL); } static TupleTableSlot * -- 2.27.0