From: Wouter Wijngaards Date: Thu, 18 Oct 2007 22:17:02 +0000 (+0000) Subject: keep cache of prealloced blocks. X-Git-Tag: release-0.6~46 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ce11690aa1fb923dfac09f97a46909d846b1ef1c;p=thirdparty%2Funbound.git keep cache of prealloced blocks. git-svn-id: file:///svn/unbound/trunk@698 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/doc/Changelog b/doc/Changelog index d474f146b..98d0aa7e3 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -13,6 +13,9 @@ - start of regional allocator code. - regional uses less memory and variables, simplified code. - remove of region-allocator. + - alloc cache keeps a cache of recently released regional blocks, + up to a maximum. + - make unit test cleanly free memory. 17 October 2007: Wouter - fixup another cycle detect and ns-addr timeout resolution bug. diff --git a/services/mesh.c b/services/mesh.c index 1ec5ca8c4..22f951e88 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -53,6 +53,7 @@ #include "util/data/msgencode.h" #include "util/timehist.h" #include "util/fptr_wlist.h" +#include "util/alloc.h" int mesh_state_compare(const void* ap, const void* bp) @@ -195,7 +196,7 @@ struct mesh_state* mesh_state_create(struct module_env* env, struct query_info* qinfo, uint16_t qflags, int prime) { - struct regional* region = regional_create(); + struct regional* region = alloc_reg_obtain(env->alloc); struct mesh_state* mstate; int i; if(!region) @@ -203,7 +204,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo, mstate = (struct mesh_state*)regional_alloc(region, sizeof(struct mesh_state)); if(!mstate) { - regional_destroy(region); + alloc_reg_release(env->alloc, region); return NULL; } memset(mstate, 0, sizeof(*mstate)); @@ -222,7 +223,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo, mstate->s.qinfo.qname = regional_alloc_init(region, qinfo->qname, qinfo->qname_len); if(!mstate->s.qinfo.qname) { - regional_destroy(region); + alloc_reg_release(env->alloc, region); return NULL; } /* remove all weird bits from qflags */ @@ -258,7 +259,7 @@ mesh_state_cleanup(struct mesh_state* mstate) mstate->s.minfo[i] = NULL; mstate->s.ext_state[i] = module_finished; } - regional_destroy(mstate->s.region); + alloc_reg_release(mstate->s.env->alloc, mstate->s.region); } void diff --git a/testcode/ldns-testpkts.c b/testcode/ldns-testpkts.c index c4e6b6c06..d11929b79 100644 --- a/testcode/ldns-testpkts.c +++ b/testcode/ldns-testpkts.c @@ -534,6 +534,8 @@ read_datafile(const char* name) verbose(1, "%s: Read %d entries\n", prog_name, entry_num); fclose(in); + ldns_rdf_deep_free(origin); + ldns_rdf_deep_free(prev_rr); return list; } diff --git a/testcode/unitverify.c b/testcode/unitverify.c index 66462c774..353aeb444 100644 --- a/testcode/unitverify.c +++ b/testcode/unitverify.c @@ -282,6 +282,7 @@ verifytest_file(const char* fname, const char* at_date) verifytest_entry(e, &alloc, region, buf, dnskey, &env, &ve); } + ub_packed_rrset_parsedelete(dnskey, &alloc); delete_entry(list); regional_destroy(region); alloc_clear(&alloc); diff --git a/util/alloc.c b/util/alloc.c index a6ac2caee..113f6a737 100644 --- a/util/alloc.c +++ b/util/alloc.c @@ -41,8 +41,11 @@ #include "config.h" #include "util/alloc.h" +#include "util/regional.h" #include "util/data/packed_rrset.h" +/** custom size of cached regional blocks */ +#define ALLOC_REG_SIZE 16384 /** number of bits for ID part of uint64, rest for number of threads. */ #define THRNUM_SHIFT 48 /* for 65k threads, 2^48 rrsets per thr. */ @@ -74,6 +77,21 @@ prealloc(struct alloc_cache* alloc) } } +/** prealloc region blocks */ +static void +prealloc_blocks(struct alloc_cache* alloc, size_t num) +{ + size_t i; + struct regional* r; + for(i=0; inext = (char*)alloc->reg_list; + alloc->reg_list = r; + alloc->num_reg_blocks ++; + } +} + void alloc_init(struct alloc_cache* alloc, struct alloc_cache* super, int thread_num) @@ -88,6 +106,11 @@ alloc_init(struct alloc_cache* alloc, struct alloc_cache* super, alloc->last_id -= 1; /* for compiler portability. */ alloc->last_id |= alloc->next_id; alloc->next_id += 1; /* because id=0 is special. */ + alloc->max_reg_blocks = 100; + alloc->num_reg_blocks = 0; + alloc->reg_list = NULL; + if(alloc->super) + prealloc_blocks(alloc, alloc->max_reg_blocks); if(!alloc->super) { lock_quick_init(&alloc->lock); lock_protect(&alloc->lock, alloc, sizeof(*alloc)); @@ -98,6 +121,7 @@ void alloc_clear(struct alloc_cache* alloc) { alloc_special_t* p, *np; + struct regional* r, *nr; if(!alloc) return; if(!alloc->super) { @@ -126,6 +150,14 @@ alloc_clear(struct alloc_cache* alloc) } alloc->quar = 0; alloc->num_quar = 0; + r = alloc->reg_list; + while(r) { + nr = (struct regional*)r->next; + free(r); + r = nr; + } + alloc->reg_list = NULL; + alloc->num_reg_blocks = 0; } uint64_t @@ -236,8 +268,8 @@ alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem) void alloc_stats(struct alloc_cache* alloc) { - log_info("%salloc: %d in cache.", alloc->super?"":"sup", - (int)alloc->num_quar); + log_info("%salloc: %d in cache, %d blocks.", alloc->super?"":"sup", + (int)alloc->num_quar, (int)alloc->num_reg_blocks); } size_t alloc_get_mem(struct alloc_cache* alloc) @@ -251,12 +283,40 @@ size_t alloc_get_mem(struct alloc_cache* alloc) for(p = alloc->quar; p; p = alloc_special_next(p)) { s += lock_get_mem(&p->entry.lock); } + s += alloc->num_reg_blocks * ALLOC_REG_SIZE; if(!alloc->super) { lock_quick_unlock(&alloc->lock); } return s; } +struct regional* +alloc_reg_obtain(struct alloc_cache* alloc) +{ + if(alloc->num_reg_blocks > 0) { + struct regional* r = alloc->reg_list; + alloc->reg_list = (struct regional*)r->next; + r->next = NULL; + alloc->num_reg_blocks--; + return r; + } + return regional_create_custom(ALLOC_REG_SIZE); +} + +void +alloc_reg_release(struct alloc_cache* alloc, struct regional* r) +{ + if(alloc->num_reg_blocks >= alloc->max_reg_blocks) { + regional_destroy(r); + return; + } + regional_free_all(r); + log_assert(r->next == NULL); + r->next = (char*)alloc->reg_list; + alloc->reg_list = r; + alloc->num_reg_blocks++; +} + /** global debug value to keep track of total memory mallocs */ size_t unbound_mem_alloc = 0; /** global debug value to keep track of total memory frees */ diff --git a/util/alloc.h b/util/alloc.h index 1bf8e4e82..8bba43e5d 100644 --- a/util/alloc.h +++ b/util/alloc.h @@ -50,6 +50,7 @@ #include "util/locks.h" struct ub_packed_rrset_key; +struct regional; /** The special type, packed rrset. Not allowed to be used for other memory */ typedef struct ub_packed_rrset_key alloc_special_t; @@ -83,6 +84,13 @@ struct alloc_cache { uint64_t next_id; /** last id number possible */ uint64_t last_id; + + /** how many regional blocks to keep back max */ + size_t max_reg_blocks; + /** how many regional blocks are kept now */ + size_t num_reg_blocks; + /** linked list of regional blocks, using regional->next */ + struct regional* reg_list; }; /** @@ -140,4 +148,18 @@ size_t alloc_get_mem(struct alloc_cache* alloc); */ void alloc_stats(struct alloc_cache* alloc); +/** + * Get a new regional for query states + * @param alloc: where to alloc it. + * @return regional for use or NULL on alloc failure. + */ +struct regional* alloc_reg_obtain(struct alloc_cache* alloc); + +/** + * Put regional for query states back into alloc cache. + * @param alloc: where to alloc it. + * @param r: regional to put back. + */ +void alloc_reg_release(struct alloc_cache* alloc, struct regional* r); + #endif /* UTIL_ALLOC_H */