keep cache of prealloced blocks.

git-svn-id: file:///svn/unbound/trunk@698 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-10-18 22:17:02 +00:00
parent 6f49c2fe55
commit ce11690aa1
6 changed files with 95 additions and 6 deletions

View file

@ -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.

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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; i<num; i++) {
r = regional_create_custom(ALLOC_REG_SIZE);
if(!r) fatal_exit("prealloc blocks: out of memory");
r->next = (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 */

View file

@ -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 */