diff options
Diffstat (limited to 'src/backend/utils/cache/catcache.c')
-rw-r--r-- | src/backend/utils/cache/catcache.c | 169 |
1 files changed, 119 insertions, 50 deletions
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index cab6291acd0..47ab410cfc2 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.86 2001/11/05 17:46:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.87 2002/02/19 20:11:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,9 +24,13 @@ #include "catalog/catname.h" #include "catalog/indexing.h" #include "miscadmin.h" +#ifdef CATCACHE_STATS +#include "storage/ipc.h" /* for on_proc_exit */ +#endif #include "utils/builtins.h" #include "utils/fmgroids.h" #include "utils/catcache.h" +#include "utils/relcache.h" #include "utils/syscache.h" @@ -94,6 +98,9 @@ static Index CatalogCacheComputeTupleHashIndex(CatCache *cache, HeapTuple tuple); static void CatalogCacheInitializeCache(CatCache *cache); static Datum cc_hashname(PG_FUNCTION_ARGS); +#ifdef CATCACHE_STATS +static void CatCachePrintStats(void); +#endif /* @@ -147,6 +154,46 @@ cc_hashname(PG_FUNCTION_ARGS) } +#ifdef CATCACHE_STATS + +static void +CatCachePrintStats(void) +{ + CatCache *cache; + long cc_searches = 0; + long cc_hits = 0; + long cc_newloads = 0; + + elog(DEBUG, "Catcache stats dump: %d/%d tuples in catcaches", + CacheHdr->ch_ntup, CacheHdr->ch_maxtup); + + for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next) + { + if (cache->cc_ntup == 0 && cache->cc_searches == 0) + continue; /* don't print unused caches */ + elog(DEBUG, "Catcache %s/%s: %d tup, %ld srch, %ld hits, %ld loads, %ld not found", + cache->cc_relname, + cache->cc_indname, + cache->cc_ntup, + cache->cc_searches, + cache->cc_hits, + cache->cc_newloads, + cache->cc_searches - cache->cc_hits - cache->cc_newloads); + cc_searches += cache->cc_searches; + cc_hits += cache->cc_hits; + cc_newloads += cache->cc_newloads; + } + elog(DEBUG, "Catcache totals: %d tup, %ld srch, %ld hits, %ld loads, %ld not found", + CacheHdr->ch_ntup, + cc_searches, + cc_hits, + cc_newloads, + cc_searches - cc_hits - cc_newloads); +} + +#endif /* CATCACHE_STATS */ + + /* * Standard routine for creating cache context if it doesn't exist yet * @@ -290,6 +337,30 @@ CatalogCacheInitializeCache(CatCache *cache) } /* + * InitCatCachePhase2 -- external interface for CatalogCacheInitializeCache + * + * The only reason to call this routine is to ensure that the relcache + * has created entries for all the catalogs and indexes referenced by + * catcaches. Therefore, open the index too. An exception is the indexes + * on pg_am, which we don't use (cf. IndexScanOK). + */ +void +InitCatCachePhase2(CatCache *cache) +{ + if (cache->cc_tupdesc == NULL) + CatalogCacheInitializeCache(cache); + + if (cache->id != AMOID && + cache->id != AMNAME) + { + Relation idesc; + + idesc = index_openr(cache->cc_indname); + index_close(idesc); + } +} + +/* * CatalogCacheComputeHashIndex */ static Index @@ -644,11 +715,11 @@ CatalogCacheFlushRelation(Oid relId) { bool isNull; - tupRelid = DatumGetObjectId( - fastgetattr(&ct->tuple, - cache->cc_reloidattr, - cache->cc_tupdesc, - &isNull)); + tupRelid = + DatumGetObjectId(fastgetattr(&ct->tuple, + cache->cc_reloidattr, + cache->cc_tupdesc, + &isNull)); Assert(!isNull); } @@ -717,21 +788,20 @@ InitCatCache(int id, CacheHdr->ch_ntup = 0; CacheHdr->ch_maxtup = MAXCCTUPLES; DLInitList(&CacheHdr->ch_lrulist); +#ifdef CATCACHE_STATS + on_proc_exit(CatCachePrintStats, 0); +#endif } /* * allocate a new cache structure + * + * Note: we assume zeroing initializes the bucket headers correctly */ cp = (CatCache *) palloc(sizeof(CatCache) + NCCBUCKETS * sizeof(Dllist)); MemSet((char *) cp, 0, sizeof(CatCache) + NCCBUCKETS * sizeof(Dllist)); /* - * initialize the cache buckets (each bucket is a list header) - */ - for (i = 0; i < NCCBUCKETS; ++i) - DLInitList(&cp->cc_bucket[i]); - - /* * 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. @@ -777,57 +847,44 @@ InitCatCache(int id, * certain system indexes that support critical syscaches. * We can't use an indexscan to fetch these, else we'll get into * infinite recursion. A plain heap scan will work, however. + * + * Once we have completed relcache initialization (signaled by + * criticalRelcachesBuilt), we don't have to worry anymore. */ static bool IndexScanOK(CatCache *cache, ScanKey cur_skey) { if (cache->id == INDEXRELID) { - static Oid indexSelfOid = InvalidOid; - - /* One-time lookup of the OID of pg_index_indexrelid_index */ - if (!OidIsValid(indexSelfOid)) - { - Relation rel; - ScanKeyData key; - HeapScanDesc sd; - HeapTuple ntp; - - rel = heap_openr(RelationRelationName, AccessShareLock); - ScanKeyEntryInitialize(&key, 0, Anum_pg_class_relname, - F_NAMEEQ, - PointerGetDatum(IndexRelidIndex)); - sd = heap_beginscan(rel, false, SnapshotNow, 1, &key); - ntp = heap_getnext(sd, 0); - if (!HeapTupleIsValid(ntp)) - elog(ERROR, "IndexScanOK: %s not found in %s", - IndexRelidIndex, RelationRelationName); - indexSelfOid = ntp->t_data->t_oid; - heap_endscan(sd); - heap_close(rel, AccessShareLock); - } - - /* Looking for pg_index_indexrelid_index? */ - if (DatumGetObjectId(cur_skey[0].sk_argument) == indexSelfOid) + /* + * Since the OIDs of indexes aren't hardwired, it's painful to + * figure out which is which. Just force all pg_index searches + * to be heap scans while building the relcaches. + */ + if (!criticalRelcachesBuilt) return false; } - else if (cache->id == AMOPSTRATEGY || - cache->id == AMPROCNUM) + else if (cache->id == AMOID || + cache->id == AMNAME) { - /* Looking for an OID or INT2 btree operator or function? */ - Oid lookup_oid = DatumGetObjectId(cur_skey[0].sk_argument); - - if (lookup_oid == OID_BTREE_OPS_OID || - lookup_oid == INT2_BTREE_OPS_OID) - return false; + /* + * Always do heap scans in pg_am, because it's so small there's + * not much point in an indexscan anyway. We *must* do this when + * initially building critical relcache entries, but we might as + * well just always do it. + */ + return false; } else if (cache->id == OPEROID) { - /* Looking for an OID comparison function? */ - Oid lookup_oid = DatumGetObjectId(cur_skey[0].sk_argument); + if (!criticalRelcachesBuilt) + { + /* Looking for an OID comparison function? */ + Oid lookup_oid = DatumGetObjectId(cur_skey[0].sk_argument); - if (lookup_oid >= MIN_OIDCMP && lookup_oid <= MAX_OIDCMP) - return false; + if (lookup_oid >= MIN_OIDCMP && lookup_oid <= MAX_OIDCMP) + return false; + } } /* Normal case, allow index scan */ @@ -861,6 +918,10 @@ SearchCatCache(CatCache *cache, if (cache->cc_tupdesc == NULL) CatalogCacheInitializeCache(cache); +#ifdef CATCACHE_STATS + cache->cc_searches++; +#endif + /* * initialize the search key information */ @@ -919,6 +980,10 @@ SearchCatCache(CatCache *cache, cache->cc_relname, hash); #endif /* CACHEDEBUG */ +#ifdef CATCACHE_STATS + cache->cc_hits++; +#endif + return &ct->tuple; } @@ -1046,6 +1111,10 @@ SearchCatCache(CatCache *cache, DLAddHead(&CacheHdr->ch_lrulist, &ct->lrulist_elem); DLAddHead(&cache->cc_bucket[hash], &ct->cache_elem); +#ifdef CATCACHE_STATS + cache->cc_newloads++; +#endif + /* * If we've exceeded the desired size of the caches, try to throw away * the least recently used entry. |