apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dean gaudet <d...@arctic.org>
Subject Re: Observations on fragmentation in SMS pools
Date Sun, 08 Jul 2001 18:19:14 GMT


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;


Mime
View raw message