alloc quar work.

git-svn-id: file:///svn/unbound/trunk@164 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-03-06 15:46:17 +00:00
parent 1a38497dbe
commit 696d38318c
3 changed files with 158 additions and 76 deletions

View File

@ -1,5 +1,6 @@
6 March 2007: Wouter
- Testbed works with threading (different machines, different options).
- alloc work, does the special type.
2 March 2007: Wouter
- do not compile fork funcs unless needed. Otherwise will give

View File

@ -42,3 +42,141 @@
#include "config.h"
#include "util/alloc.h"
/** prealloc some entries in the cache. To minimize contention.
* @param alloc: the structure to fill up.
*/
static void
prealloc(struct alloc_cache* alloc)
{
alloc_special_t* p;
int i;
for(i=0; i<ALLOC_SPECIAL_MAX; i++) {
if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t))))
fatal_exit("prealloc: out of memory");
alloc_special_next(p) = alloc->quar;
alloc->quar = p;
alloc->num_quar++;
}
}
void
alloc_init(struct alloc_cache* alloc, struct alloc_cache* super)
{
memset(alloc, 0, sizeof(*alloc));
alloc->super = super;
lock_quick_init(&alloc->lock);
}
void
alloc_delete(struct alloc_cache* alloc)
{
alloc_special_t* p, *np;
if(!alloc)
return;
lock_quick_destroy(&alloc->lock);
if(alloc->super && alloc->quar) {
/* push entire list into super */
p = alloc->quar;
while(alloc_special_next(p)) /* find last */
p = alloc_special_next(p);
lock_quick_lock(&alloc->super->lock);
alloc_special_next(p) = alloc->super->quar;
alloc->super->quar = alloc->quar;
alloc->super->num_quar += alloc->num_quar;
lock_quick_unlock(&alloc->super->lock);
} else {
/* free */
p = alloc->quar;
while(p) {
np = alloc_special_next(p);
free(p);
p = np;
}
}
alloc->quar = 0;
alloc->num_quar = 0;
}
alloc_special_t*
alloc_special_obtain(struct alloc_cache* alloc)
{
alloc_special_t* p;
log_assert(alloc);
/* see if in local cache */
if(alloc->quar) {
p = alloc->quar;
alloc->quar = alloc_special_next(p);
alloc->num_quar--;
alloc->special_allocated++;
return p;
}
/* see if in global cache */
if(alloc->super) {
lock_quick_lock(&alloc->super->lock);
if((p = alloc->super->quar)) {
alloc->super->quar = alloc_special_next(p);
alloc->super->num_quar--;
}
lock_quick_unlock(&alloc->super->lock);
if(p) {
alloc->special_allocated++;
return p;
}
}
/* allocate new */
prealloc(alloc);
if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t))))
fatal_exit("alloc_special_obtain: out of memory");
alloc->special_allocated++;
return p;
}
/** push mem and some more items to the super */
static void
pushintosuper(struct alloc_cache* alloc, alloc_special_t* mem)
{
int i;
alloc_special_t *p = alloc->quar;
log_assert(p);
log_assert(alloc && alloc->super &&
alloc->num_quar >= ALLOC_SPECIAL_MAX);
/* push ALLOC_SPECIAL_MAX/2 after mem */
alloc_special_next(mem) = alloc->quar;
for(i=1; i<ALLOC_SPECIAL_MAX/2; i++) {
p = alloc_special_next(p);
}
alloc->quar = alloc_special_next(p);
alloc->num_quar -= ALLOC_SPECIAL_MAX/2;
lock_quick_lock(&alloc->super->lock);
alloc_special_next(p) = alloc->super->quar;
alloc->super->quar = mem;
alloc->super->num_quar += ALLOC_SPECIAL_MAX/2 + 1;
lock_quick_unlock(&alloc->super->lock);
}
void
alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem)
{
log_assert(alloc);
if(!mem)
return;
if(alloc->super && alloc->num_quar >= ALLOC_SPECIAL_MAX) {
/* push it to the super structure */
alloc->special_allocated --;
pushintosuper(alloc, mem);
return;
}
alloc_special_next(mem) = alloc->quar;
alloc->quar = mem;
alloc->num_quar++;
alloc->special_allocated--;
}
void
alloc_stats(struct alloc_cache* alloc)
{
log_info("%salloc: %d allocated, %d in cache.", alloc->super?"":"sup",
(int)alloc->special_allocated, (int)alloc->num_quar);
}

View File

@ -42,10 +42,6 @@
* o Avoid locking costs of getting global lock to call malloc().
* o The packed rrset type needs to be kept on special freelists,
* so that they are reused for other packet rrset allocations.
* o This service is not there to improve speed of malloc.
* Some caching is performed to help avoid locking costs.
* o This service does not prevent fragmentation.
* The caching will help somewhat for this.
*
* Design choices:
* o The global malloc/free is used to handle fragmentation, etc.
@ -61,120 +57,67 @@
#include "util/locks.h"
/** all allocations are in multiples of this size */
#define ALLOC_ALIGN 32 /* bytes */
/**
* This size and smaller is kept in cached lists by size.
* Must be a multiple of ALLOC_ALIGN.
*/
#define ALLOC_LARGESIZE 1024 /* bytes */
/** number of bins */
#define ALLOC_BINS (ALLOC_LARGESIZE / ALLOC_ALIGN)
/** The special type, packed rrset. Not allowed to be used for other memory */
typedef uint64_t alloc_special_t;
/** clean the special type. Pass pointer. */
#define alloc_special_clean(x) memset(x, 0, sizeof(alloc_special_t))
/** access next pointer. (in available spot). Pass pointer. */
#define alloc_special_next(x) ((alloc_special_t*)(*(x)))
#define alloc_special_next(x) (*((alloc_special_t**)(x)))
/** The number of cached items. */
#define ALLOC_CACHENUM 10 /* memory blocks */
/** how many blocks to cache locally. */
#define ALLOC_SPECIAL_MAX 10
/** Preallocated per thread. This number for every size. */
#define ALLOC_PREALLOC 32 /* memory blocks */
/** shorthand */
typedef struct alloc_cache alloc_t;
/**
* Structure that provides caching based on size. Used one per thread.
* Structure that provides allocation. Use one per thread.
* The one on top has a NULL super pointer.
*/
struct alloc_cache {
/** lock, only used for the super. */
lock_quick_t lock;
/** global allocator above this one. NULL for none (malloc/free) */
struct alloc_super* super;
/** singly linked lists per size: [0]32, [1]64, ... [n-1]LARGESIZE */
void* bins[ALLOC_BINS];
/** the number of items per bin. */
size_t nums[ALLOC_BINS];
struct alloc_cache* super;
/** singly linked lists of special type. These are free for use. */
alloc_special_t* quar;
/** number of items in quarantine. */
size_t num_quar;
/* some statistics */
/** amount allocated. */
size_t bytes_allocated;
/** number of items allocated. */
size_t items_allocated;
/** wasted space due to assigning oversized aligned blocks. */
size_t internal_frag;
/** amount in cache. */
size_t bytes_in_bins;
/** number of special type allocated */
size_t special_allocated;
};
/**
* Structure with lock to provide global cache of special items and allocs.
*/
struct alloc_super {
/** lock for single access. */
lock_quick_t lock;
/** singly linked lists of special type. These are free for use. */
alloc_special_t* quar;
/** number of items in quarantine. */
size_t num_quar;
};
/**
* Init super alloc. (zeroes the struct, inits the lock).
* @param super: to init.
*/
void asuper_init(struct alloc_super* super);
/**
* Init alloc (zeroes the struct).
* @param alloc: this parameter is allocated by the caller.
* @param super: super to use (init that before with super_init).
*/
void alloc_init(alloc_t* alloc, struct alloc_super* super);
void alloc_init(struct alloc_cache* alloc, struct alloc_cache* super);
/**
* Free the alloc. Pushes all the cached items into the super structure.
* Or deletes them if super is NULL.
* Does not free the alloc struct itself.
* @param alloc: is almost zeroed on exit (except some stats).
*/
void alloc_delete(alloc_t* alloc);
/**
* Allocate memory
* @param alloc: where to alloc it.
* @param size: how much.
* @return: memory block. Will not return NULL (instead fatal_exit).
*/
void* alloc_alloc(alloc_t* alloc, size_t size);
/**
* Free memory.
* @param alloc: where to alloc it.
* @param mem: block to free.
*/
void alloc_free(alloc_t* alloc, void* mem);
void alloc_delete(struct alloc_cache* alloc);
/**
* Get a new special_t element.
* @param alloc: where to alloc it.
* @return: memory block. Will not return NULL (instead fatal_exit).
*/
alloc_special_t* alloc_special_alloc(alloc_t* alloc);
alloc_special_t* alloc_special_obtain(struct alloc_cache* alloc);
/**
* Return special_t back to pool.
* @param alloc: where to alloc it.
* @param mem: block to free.
*/
void alloc_special_free(alloc_t* alloc, alloc_special_t* mem);
void alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem);
/**
* Print debug information (statistics).
* @param alloc: on what alloc.
*/
void alloc_stats(struct alloc_cache* alloc);
#endif /* UTIL_ALLOC_H */