On Sun, 8 Jul 2001, Justin Erenkrantz wrote:
> Also, I did try having the pools use malloc/free directly > (ALLOC_USE_MALLOC) and the performance was dreadful. At least on > Solaris. -- justin yes, ALLOC_USE_MALLOC is dreadful -- that's not what i meant. what i mean is something like the below patch, which i haven't even tried to compile or test ;) (the patch needs work to rescue some of the debugging code in new_block). it removes block_freelist and uses malloc/free for blocks. this is much less expensive than malloc/free on each allocation (amortization). -dean Index: apr_pools.c =================================================================== RCS file: /home/cvs/apr/memory/unix/apr_pools.c,v retrieving revision 1.100 diff -u -r1.100 apr_pools.c --- apr_pools.c 2001/07/07 22:23:54 1.100 +++ apr_pools.c 2001/07/08 18:17:36 @@ -248,7 +248,6 @@ /* * Static cells for managing our internal synchronisation. */ -static union block_hdr *block_freelist = NULL; #if APR_HAS_THREADS static apr_lock_t *alloc_mutex; @@ -417,120 +416,20 @@ static void free_blocks(union block_hdr *blok) { -#ifdef ALLOC_USE_MALLOC union block_hdr *next; for ( ; blok; blok = next) { next = blok->h.next; DO_FREE(blok); } -#else /* ALLOC_USE_MALLOC */ - -#ifdef ALLOC_STATS - unsigned num_blocks; -#endif /* ALLOC_STATS */ - - /* - * First, put new blocks at the head of the free list --- - * we'll eventually bash the 'next' pointer of the last block - * in the chain to point to the free blocks we already had. - */ - - union block_hdr *old_free_list; - - if (blok == NULL) { - return; /* Sanity check --- freeing empty pool? */ - } - -#if APR_HAS_THREADS - if (alloc_mutex) { - apr_lock_acquire(alloc_mutex); - } -#endif - old_free_list = block_freelist; - block_freelist = blok; - - /* - * Next, adjust first_avail pointers of each block --- have to do it - * sooner or later, and it simplifies the search in new_block to do it - * now. - */ - -#ifdef ALLOC_STATS - num_blocks = 1; -#endif /* ALLOC_STATS */ - - while (blok->h.next != NULL) { - -#ifdef ALLOC_STATS - ++num_blocks; -#endif /* ALLOC_STATS */ - - chk_on_blk_list(blok, old_free_list); - blok->h.first_avail = (char *) (blok + 1); - debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail); -#ifdef APR_POOL_DEBUG - blok->h.owning_pool = FREE_POOL; -#endif /* APR_POOL_DEBUG */ - blok = blok->h.next; - } - - chk_on_blk_list(blok, old_free_list); - blok->h.first_avail = (char *) (blok + 1); - debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail); -#ifdef APR_POOL_DEBUG - blok->h.owning_pool = FREE_POOL; -#endif /* APR_POOL_DEBUG */ - - /* Finally, reset next pointer to get the old free blocks back */ - - blok->h.next = old_free_list; - -#ifdef ALLOC_STATS - if (num_blocks > max_blocks_in_one_free) { - max_blocks_in_one_free = num_blocks; - } - ++num_free_blocks_calls; - num_blocks_freed += num_blocks; -#endif /* ALLOC_STATS */ - -#if APR_HAS_THREADS - if (alloc_mutex) { - apr_lock_release(alloc_mutex); - } -#endif /* APR_HAS_THREADS */ -#endif /* ALLOC_USE_MALLOC */ } /* - * Get a new block, from our own free list if possible, from the system - * if necessary. Must be called with alarms blocked. + * get a new block from the system */ static union block_hdr *new_block(apr_size_t min_size, apr_abortfunc_t abortfunc) { - union block_hdr **lastptr = &block_freelist; - union block_hdr *blok = block_freelist; - - /* First, see if we have anything of the required size - * on the free list... - */ - - while (blok != NULL) { - if ((apr_ssize_t)min_size + BLOCK_MINFREE <= blok->h.endp - blok->h.first_avail) { - *lastptr = blok->h.next; - blok->h.next = NULL; - debug_verify_filled(blok->h.first_avail, blok->h.endp, - "[new_block] Ouch! Someone trounced a block " - "on the free list!\n"); - return blok; - } - else { - lastptr = &blok->h.next; - blok = blok->h.next; - } - } - - /* Nope. */ + union block_hdr *blok; min_size += BLOCK_MINFREE; blok = malloc_block((min_size > BLOCK_MINALLOC) @@ -586,7 +485,6 @@ union block_hdr *blok; apr_pool_t *new_pool; - #if APR_HAS_THREADS if (alloc_mutex) { apr_lock_acquire(alloc_mutex); @@ -960,7 +858,7 @@ APR_DECLARE(apr_size_t) apr_pool_free_blocks_num_bytes(void) { - return bytes_in_block_list(block_freelist); + return 0; } /* the unix linker defines this symbol as the last byte + 1 of @@ -1255,13 +1153,7 @@ cur_len = strp - blok->h.first_avail; /* must try another blok */ -#if APR_HAS_THREADS - apr_lock_acquire(alloc_mutex); -#endif nblok = new_block(2 * cur_len, NULL); -#if APR_HAS_THREADS - apr_lock_release(alloc_mutex); -#endif memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len); ps->vbuff.curpos = nblok->h.first_avail + cur_len; /* save a byte for the NUL terminator */ @@ -1270,14 +1162,7 @@ /* did we allocate the current blok? if so free it up */ if (ps->got_a_new_block) { debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail); -#if APR_HAS_THREADS - apr_lock_acquire(alloc_mutex); -#endif - blok->h.next = block_freelist; - block_freelist = blok; -#if APR_HAS_THREADS - apr_lock_release(alloc_mutex); -#endif + DO_FREE(blok); } ps->blok = nblok; ps->got_a_new_block = 1;