diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-14 19:16:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-14 19:16:24 +0000 |
commit | 2a0f262beff32ba86bcb58f3273214e5d0517c09 (patch) | |
tree | 24c0ad10dab36bbd5c22743d3c88c4e0ccd5bc65 /src/backend/utils/cache | |
parent | Releasing progress-linux version 16.2-2~progress7.99u1. (diff) | |
download | postgresql-16-2a0f262beff32ba86bcb58f3273214e5d0517c09.tar.xz postgresql-16-2a0f262beff32ba86bcb58f3273214e5d0517c09.zip |
Merging upstream version 16.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r-- | src/backend/utils/cache/catcache.c | 143 |
1 files changed, 120 insertions, 23 deletions
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index e85e564..a2ebb50 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -89,6 +89,8 @@ static void CatCachePrintStats(int code, Datum arg); #endif static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct); static void CatCacheRemoveCList(CatCache *cache, CatCList *cl); +static void RehashCatCache(CatCache *cp); +static void RehashCatCacheLists(CatCache *cp); static void CatalogCacheInitializeCache(CatCache *cache); static CatCTup *CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp, SysScanDesc scandesc, @@ -393,6 +395,7 @@ CatCachePrintStats(int code, Datum arg) long cc_neg_hits = 0; long cc_newloads = 0; long cc_invals = 0; + long cc_nlists = 0; long cc_lsearches = 0; long cc_lhits = 0; @@ -402,7 +405,7 @@ CatCachePrintStats(int code, Datum arg) if (cache->cc_ntup == 0 && cache->cc_searches == 0) continue; /* don't print unused caches */ - elog(DEBUG2, "catcache %s/%u: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %ld lsrch, %ld lhits", + elog(DEBUG2, "catcache %s/%u: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %d lists, %ld lsrch, %ld lhits", cache->cc_relname, cache->cc_indexoid, cache->cc_ntup, @@ -414,6 +417,7 @@ CatCachePrintStats(int code, Datum arg) cache->cc_searches - cache->cc_hits - cache->cc_neg_hits - cache->cc_newloads, cache->cc_searches - cache->cc_hits - cache->cc_neg_hits, cache->cc_invals, + cache->cc_nlist, cache->cc_lsearches, cache->cc_lhits); cc_searches += cache->cc_searches; @@ -421,10 +425,11 @@ CatCachePrintStats(int code, Datum arg) cc_neg_hits += cache->cc_neg_hits; cc_newloads += cache->cc_newloads; cc_invals += cache->cc_invals; + cc_nlists += cache->cc_nlist; cc_lsearches += cache->cc_lsearches; cc_lhits += cache->cc_lhits; } - elog(DEBUG2, "catcache totals: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %ld lsrch, %ld lhits", + elog(DEBUG2, "catcache totals: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %ld lists, %ld lsrch, %ld lhits", CacheHdr->ch_ntup, cc_searches, cc_hits, @@ -434,6 +439,7 @@ CatCachePrintStats(int code, Datum arg) cc_searches - cc_hits - cc_neg_hits - cc_newloads, cc_searches - cc_hits - cc_neg_hits, cc_invals, + cc_nlists, cc_lsearches, cc_lhits); } @@ -522,6 +528,8 @@ CatCacheRemoveCList(CatCache *cache, CatCList *cl) cache->cc_keyno, cl->keys); pfree(cl); + + --cache->cc_nlist; } @@ -560,14 +568,19 @@ CatCacheInvalidate(CatCache *cache, uint32 hashValue) * Invalidate *all* CatCLists in this cache; it's too hard to tell which * searches might still be correct, so just zap 'em all. */ - dlist_foreach_modify(iter, &cache->cc_lists) + for (int i = 0; i < cache->cc_nlbuckets; i++) { - CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur); + dlist_head *bucket = &cache->cc_lbucket[i]; - if (cl->refcount > 0) - cl->dead = true; - else - CatCacheRemoveCList(cache, cl); + dlist_foreach_modify(iter, bucket) + { + CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur); + + if (cl->refcount > 0) + cl->dead = true; + else + CatCacheRemoveCList(cache, cl); + } } /* @@ -640,14 +653,19 @@ ResetCatalogCache(CatCache *cache) int i; /* Remove each list in this cache, or at least mark it dead */ - dlist_foreach_modify(iter, &cache->cc_lists) + for (i = 0; i < cache->cc_nlbuckets; i++) { - CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur); + dlist_head *bucket = &cache->cc_lbucket[i]; - if (cl->refcount > 0) - cl->dead = true; - else - CatCacheRemoveCList(cache, cl); + dlist_foreach_modify(iter, bucket) + { + CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur); + + if (cl->refcount > 0) + cl->dead = true; + else + CatCacheRemoveCList(cache, cl); + } } /* Remove each tuple in this cache, or at least mark it dead */ @@ -812,6 +830,12 @@ InitCatCache(int id, cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head)); /* + * Many catcaches never receive any list searches. Therefore, we don't + * allocate the cc_lbuckets till we get a list search. + */ + cp->cc_lbucket = NULL; + + /* * initialize the cache's relation information for the relation * corresponding to this cache, and initialize some of the new cache's * other internal fields. But don't open the relation yet. @@ -823,7 +847,9 @@ InitCatCache(int id, cp->cc_relisshared = false; /* temporary */ cp->cc_tupdesc = (TupleDesc) NULL; cp->cc_ntup = 0; + cp->cc_nlist = 0; cp->cc_nbuckets = nbuckets; + cp->cc_nlbuckets = 0; cp->cc_nkeys = nkeys; for (i = 0; i < nkeys; ++i) cp->cc_keyno[i] = key[i]; @@ -886,6 +912,44 @@ RehashCatCache(CatCache *cp) } /* + * Enlarge a catcache's list storage, doubling the number of buckets. + */ +static void +RehashCatCacheLists(CatCache *cp) +{ + dlist_head *newbucket; + int newnbuckets; + int i; + + elog(DEBUG1, "rehashing catalog cache id %d for %s; %d lists, %d buckets", + cp->id, cp->cc_relname, cp->cc_nlist, cp->cc_nlbuckets); + + /* Allocate a new, larger, hash table. */ + newnbuckets = cp->cc_nlbuckets * 2; + newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head)); + + /* Move all entries from old hash table to new. */ + for (i = 0; i < cp->cc_nlbuckets; i++) + { + dlist_mutable_iter iter; + + dlist_foreach_modify(iter, &cp->cc_lbucket[i]) + { + CatCList *cl = dlist_container(CatCList, cache_elem, iter.cur); + int hashIndex = HASH_INDEX(cl->hash_value, newnbuckets); + + dlist_delete(iter.cur); + dlist_push_head(&newbucket[hashIndex], &cl->cache_elem); + } + } + + /* Switch to the new array. */ + pfree(cp->cc_lbucket); + cp->cc_nlbuckets = newnbuckets; + cp->cc_lbucket = newbucket; +} + +/* * CatalogCacheInitializeCache * * This function does final initialization of a catcache: obtain the tuple @@ -1527,7 +1591,9 @@ SearchCatCacheList(CatCache *cache, Datum v4 = 0; /* dummy last-column value */ Datum arguments[CATCACHE_MAXKEYS]; uint32 lHashValue; + Index lHashIndex; dlist_iter iter; + dlist_head *lbucket; CatCList *cl; CatCTup *ct; List *volatile ctlist; @@ -1541,7 +1607,7 @@ SearchCatCacheList(CatCache *cache, /* * one-time startup overhead for each cache */ - if (cache->cc_tupdesc == NULL) + if (unlikely(cache->cc_tupdesc == NULL)) CatalogCacheInitializeCache(cache); Assert(nkeys > 0 && nkeys < cache->cc_nkeys); @@ -1557,11 +1623,36 @@ SearchCatCacheList(CatCache *cache, arguments[3] = v4; /* - * compute a hash value of the given keys for faster search. We don't - * presently divide the CatCList items into buckets, but this still lets - * us skip non-matching items quickly most of the time. + * If we haven't previously done a list search in this cache, create the + * bucket header array; otherwise, consider whether it's time to enlarge + * it. + */ + if (cache->cc_lbucket == NULL) + { + /* Arbitrary initial size --- must be a power of 2 */ + int nbuckets = 16; + + cache->cc_lbucket = (dlist_head *) + MemoryContextAllocZero(CacheMemoryContext, + nbuckets * sizeof(dlist_head)); + /* Don't set cc_nlbuckets if we get OOM allocating cc_lbucket */ + cache->cc_nlbuckets = nbuckets; + } + else + { + /* + * If the hash table has become too full, enlarge the buckets array. + * Quite arbitrarily, we enlarge when fill factor > 2. + */ + if (cache->cc_nlist > cache->cc_nlbuckets * 2) + RehashCatCacheLists(cache); + } + + /* + * Find the hash bucket in which to look for the CatCList. */ lHashValue = CatalogCacheComputeHashValue(cache, nkeys, v1, v2, v3, v4); + lHashIndex = HASH_INDEX(lHashValue, cache->cc_nlbuckets); /* * scan the items until we find a match or exhaust our list @@ -1569,7 +1660,8 @@ SearchCatCacheList(CatCache *cache, * 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. */ - dlist_foreach(iter, &cache->cc_lists) + lbucket = &cache->cc_lbucket[lHashIndex]; + dlist_foreach(iter, lbucket) { cl = dlist_container(CatCList, cache_elem, iter.cur); @@ -1589,13 +1681,13 @@ SearchCatCacheList(CatCache *cache, continue; /* - * We found a matching list. Move the list to the front of the - * cache's list-of-lists, to speed subsequent searches. (We do not + * We found a matching list. Move the list to the front of the list + * for its hashbucket, so as to speed subsequent searches. (We do not * move the members to the fronts of their hashbucket lists, however, * since there's no point in that unless they are searched for * individually.) */ - dlist_move_head(&cache->cc_lists, &cl->cache_elem); + dlist_move_head(lbucket, &cl->cache_elem); /* Bump the list's refcount and return it */ ResourceOwnerEnlargeCatCacheListRefs(CurrentResourceOwner); @@ -1806,7 +1898,12 @@ SearchCatCacheList(CatCache *cache, } Assert(i == nmembers); - dlist_push_head(&cache->cc_lists, &cl->cache_elem); + /* + * Add the CatCList to the appropriate bucket, and count it. + */ + dlist_push_head(lbucket, &cl->cache_elem); + + cache->cc_nlist++; /* Finally, bump the list's refcount and return it */ cl->refcount++; |