]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
alloc quar work.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 6 Mar 2007 15:46:17 +0000 (15:46 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 6 Mar 2007 15:46:17 +0000 (15:46 +0000)
git-svn-id: file:///svn/unbound/trunk@164 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
util/alloc.c
util/alloc.h

index a11a15d29875bcf13fb13fbcb768b9a6e67f5b1f..57ac174b1fd980a7dd6559f00e7a2f7c95c20d5f 100644 (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
index 9e17bd2daf6f54a0fa742d6fe62d562e2ee0b140..af6066700554800c9d21bbb47f92b3a7c4761c3a 100644 (file)
 #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);
+}
index d1ccd66966d58cec9ceeca51dcf0837798d33a9d..2801c8e894d03e65a1339a015a62d0ae37f99ac0 100644 (file)
  *     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.
 
 #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 */