From a9af93fcb9ccf6e120c70e08165f54d5fce44db4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Wed, 26 Sep 2012 18:43:06 +0200 Subject: [PATCH] Core: Added a dynamic cache size threshold for compile_memsearcher(). The internal cache for compile_memsearcher() could grow very large before the gc would clear some of its entries (each entry has a size of ~16KB). It now has a dynamic threshold for when it clears the cache on its own. --- src/pike_search.c | 6 +++++ src/pike_search_engine.c | 50 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/pike_search.c b/src/pike_search.c index ad666796e0..154d83329a 100644 --- a/src/pike_search.c +++ b/src/pike_search.c @@ -23,6 +23,12 @@ ptrdiff_t pike_search_struct_offset; #define OB2MSEARCH(O) ((struct pike_mem_searcher *)((O)->storage+pike_search_struct_offset)) #define THIS_MSEARCH ((struct pike_mem_searcher *)(Pike_fp->current_storage)) +/* NB: We use the least significant bit of memsearch_cache_threshold + * to indicate whether we are at MIN_MEMSEARCH_THRESHOLD or not. + */ +#define MIN_MEMSEARCH_THRESHOLD 128 +static int memsearch_cache_threshold; + static struct mapping *memsearch_cache; static struct program *pike_search_program; diff --git a/src/pike_search_engine.c b/src/pike_search_engine.c index 0cf5668f1b..305f039ef1 100644 --- a/src/pike_search_engine.c +++ b/src/pike_search_engine.c @@ -313,6 +313,56 @@ SearchMojt NameN(compile_memsearcher)(NCHAR *needle, return s->mojt; } } + /* Paranoia: Junk entry in the mapping. Remove it. */ + SET_SVAL(stmp, T_STRING, 0, string, hashkey); + map_delete(memsearch_cache, &stmp); + } + + if (memsearch_cache->data->size >= memsearch_cache_threshold) { + /* Perform a gc of all Search objects that only are + * referenced from the cache. + * Allow the cache to grow to double the size before + * the next synchronous gc. + */ + struct keypair *k = NULL; + struct mapping_data *md = memsearch_cache->data; + int e; + int count = 0; + /* NB: We inline some stuff from mapping.c here to avoid copying the md. + */ + for (e=0; e < md->hashsize; e++) { + struct keypair **prev; + for(prev = md->hash + e; (k = *prev);) { + count++; + if ((TYPEOF(k->val) <= MAX_REF_TYPE) && + (*k->val.u.refs == 1)) { + /* map_delete(memsearch_cache, &k->ind); */ + *prev = k->next; + free_svalue(&k->ind); + free_svalue(&k->val); + mapping_free_keypair(md, k); + md->size--; + continue; + } else if (count < 10) { + // locate_references(k->val.u.refs); + } + prev = &k->next; + } + } + memsearch_cache_threshold = (memsearch_cache->data->size<<1) | 1; + if (memsearch_cache_threshold < MIN_MEMSEARCH_THRESHOLD) { + memsearch_cache_threshold = MIN_MEMSEARCH_THRESHOLD; + } + } else if ((memsearch_cache_threshold & 1) && + (memsearch_cache->data->size<<2 < memsearch_cache_threshold)) { + /* The real gc() has run and zapped some of our entries. + * Assume that all entries left in the cache have more than + * one reference. + */ + memsearch_cache_threshold = (memsearch_cache->data->size<<1) | 1; + if (memsearch_cache_threshold < MIN_MEMSEARCH_THRESHOLD) { + memsearch_cache_threshold = MIN_MEMSEARCH_THRESHOLD; + } } o=low_clone(pike_search_program); -- GitLab