# New Ticket Created by  Mike Lambert 
# Please include the string:  [netlabs #634]
# in the subject line of all future correspondence about this issue. 
# <URL: http://bugs6.perl.org/rt2/Ticket/Display.html?id=634 >


Peter recently submitted a patch to RT that uses a linked-list for free
headers. Here are before and after results:

                        before          after
gc_alloc_new            4.155999        4.016
gc_alloc_reuse          16.574          12.648002
gc_generations          4.025           3.975001
gc_header_new           3.686           3.986
gc_header_reuse         5.577999        4.175998
gc_waves_headers        3.815002        3.595999
gc_waves_sizeable_data  8.383002        8.381999
gc_waves_sizeable_hdrs  5.668           5.396999

We win on the header-intensive stuff. Not sure why it would be slower on
the gc_header_new tests. My best guess is that we know are touching the
contents of the buffer header, which we weren't doing before. And when we
allocate a bunch of new headers, we have to explcitly free them all, which
involves touching the first pointer of every buffer in that memory, as
opposed to one pointer in the Parrot_allocated memory we used before.

IMO, the gc_alloc_reuse and gc_header_reuse benchmarks more than
outweigh gc_header_new.

The portion of Peter's patch to do just this change is included below.

Mike Lambert

Index: resources.c
===================================================================
RCS file: /cvs/public/parrot/resources.c,v
retrieving revision 1.60
diff -u -r1.60 resources.c
--- resources.c 26 May 2002 20:20:08 -0000      1.60
+++ resources.c 29 May 2002 07:08:26 -0000
@@ -41,28 +41,15 @@

 /* Create a new tracked resource pool */
 static struct Resource_Pool *
-new_resource_pool(struct Parrot_Interp *interpreter, size_t free_pool_size,
+new_resource_pool(struct Parrot_Interp *interpreter,
                   size_t unit_size, size_t units_per_alloc,
              void (*replenish)(struct Parrot_Interp *, struct
Resource_Pool *),
                   struct Memory_Pool *mem_pool)
 {
     struct Resource_Pool *pool;
-    size_t temp_len;

     pool = mem_sys_allocate(sizeof(struct Resource_Pool));
-    temp_len = free_pool_size * sizeof(void *);
-    if (interpreter->arena_base->buffer_header_pool) {
-        pool->free_pool_buffer = new_buffer_header(interpreter);
-    }
-    else {
-        pool->free_pool_buffer = mem_sys_allocate(sizeof(Buffer));
-    }
-    pool->free_pool_buffer->bufstart =
-        mem_allocate(interpreter, &temp_len,
-                     interpreter->arena_base->memory_pool);
-    pool->free_pool_buffer->buflen = temp_len;
-    pool->free_pool_buffer->flags = BUFFER_immune_FLAG;
-    pool->free_pool_size = temp_len / sizeof(void *);
+    pool->free_list = NULL;
     pool->free_entries = 0;
     pool->unit_size = unit_size;
     pool->units_per_alloc = units_per_alloc;
@@ -72,28 +59,6 @@
     return pool;
 }

-/* Expand free pool to accomdate at least n additional entries
- * Currently, the minimum expansion is 20% of the current size
-*/
-static void
-expand_free_pool(struct Parrot_Interp *interpreter,
-                 struct Resource_Pool *pool, size_t n)
-{
-    size_t growth;
-
-    if (pool->free_pool_size - pool->free_entries < n) {
-        growth = (n - (pool->free_pool_size - pool->free_entries)) *
-                 sizeof(void *);
-        if (growth < pool->free_pool_buffer->buflen / 5) {
-            growth = pool->free_pool_buffer->buflen / 5;
-        }
-        Parrot_reallocate(interpreter, pool->free_pool_buffer,
-                          pool->free_pool_buffer->buflen + growth);
-        pool->free_pool_size += (growth / sizeof(void *));
-    }
-}
-
-
 /* Add entry to free pool
  * Requires that any object-specific processing (eg flag setting, statistics)
  * has already been done by the caller
@@ -102,20 +67,8 @@
 add_to_free_pool(struct Parrot_Interp *interpreter,
                  struct Resource_Pool *pool, void *to_add)
 {
-    void **temp_ptr;
-
-    if (pool->free_pool_size == pool->free_entries) {
-        expand_free_pool(interpreter, pool, 1);
-    }
-
-#ifdef GC_DEBUG
-    Parrot_go_collect(interpreter);
-#endif
-
-    /* Okay, so there's space. Add the header on */
-    temp_ptr = pool->free_pool_buffer->bufstart;
-    temp_ptr += pool->free_entries;
-    *temp_ptr = to_add;
+    *(void **)to_add = pool->free_list;
+    pool->free_list = to_add;
     pool->free_entries++;
 }

@@ -127,7 +80,7 @@
 get_from_free_pool(struct Parrot_Interp *interpreter,
                    struct Resource_Pool *pool)
 {
-    void ** ptr;
+    void *ptr;

     if (!pool->free_entries) {
         Parrot_do_dod_run(interpreter);
@@ -140,9 +93,10 @@
         return NULL;
     }

-    ptr = pool->free_pool_buffer->bufstart;
-    ptr += --pool->free_entries;
-    return *ptr;
+    ptr = pool->free_list;
+    pool->free_list = *(void **)ptr;
+    pool->free_entries--;
+    return ptr;
 }

 /* We have no more headers on the free header pool. Go allocate more
@@ -175,7 +129,6 @@
     /* Note it in our stats */
     interpreter->total_PMCs += pool->units_per_alloc;

-    expand_free_pool(interpreter, pool, pool->units_per_alloc);
     cur_pmc = new_arena->start_PMC;
     for (i = 0; i < pool->units_per_alloc; i++) {
         cur_pmc->flags = PMC_on_free_list_FLAG;
@@ -253,7 +206,6 @@
     /* Note it in our stats */
     interpreter->total_Buffers += pool->units_per_alloc;

-    expand_free_pool(interpreter, pool, pool->units_per_alloc);
     cur_buffer = new_arena->start_Buffer;
     for (i = 0; i < pool->units_per_alloc; i++) {
         cur_buffer->flags = BUFFER_on_free_list_FLAG;
@@ -625,34 +577,28 @@

     /* Init the buffer header pool - this must be the first pool created!
*/
     interpreter->arena_base->buffer_header_pool =
-        new_resource_pool(interpreter, 256, sizeof(Buffer),
+        new_resource_pool(interpreter, sizeof(Buffer),
                           BUFFER_HEADERS_PER_ALLOC,
                           alloc_more_buffer_headers,
                           interpreter->arena_base->memory_pool);
-    /* Re-allocate the temporary buffer header from the new pool */
-    old_b = interpreter->arena_base->buffer_header_pool->free_pool_buffer;
-    new_b = new_buffer_header(interpreter);
-    mem_sys_memcopy(new_b, old_b, sizeof(Buffer));
-    interpreter->arena_base->buffer_header_pool->free_pool_buffer = new_b;
-    mem_sys_free(old_b);
-
+
     /* Init the string header pool */
     interpreter->arena_base->string_header_pool =
-        new_resource_pool(interpreter, 256, sizeof(STRING),
+        new_resource_pool(interpreter, sizeof(STRING),
                           STRING_HEADERS_PER_ALLOC,
                           alloc_more_buffer_headers,
                           interpreter->arena_base->string_pool);

     /* Init the PMC header pool */
     interpreter->arena_base->pmc_pool =
-        new_resource_pool(interpreter, 256, sizeof(PMC),
+        new_resource_pool(interpreter, sizeof(PMC),
                           PMC_HEADERS_PER_ALLOC,
                           alloc_more_pmc_headers,
                           NULL);

     /* Init the constant string header pool */
     interpreter->arena_base->constant_string_header_pool =
-        new_resource_pool(interpreter, 256, sizeof(STRING),
+        new_resource_pool(interpreter, sizeof(STRING),
                           STRING_HEADERS_PER_ALLOC,
                           alloc_more_buffer_headers,
                           interpreter->arena_base->constant_string_pool);
@@ -687,7 +633,7 @@

     if (sized_pools[idx] == NULL)
         sized_pools[idx] =
-            new_resource_pool(interpreter, 256, unit_size,
+            new_resource_pool(interpreter, unit_size,
                               SIZED_HEADERS_PER_ALLOC,
                               alloc_more_buffer_headers,
                               interpreter->arena_base->memory_pool);
Index: include/parrot/resources.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/resources.h,v
retrieving revision 1.32
diff -u -r1.32 resources.h
--- include/parrot/resources.h  24 May 2002 16:11:10 -0000      1.32
+++ include/parrot/resources.h  29 May 2002 07:08:27 -0000
@@ -81,11 +81,10 @@
 /* Tracked resource pool */
 struct Resource_Pool {
     void *last_Arena;
-    Buffer *free_pool_buffer;
+    void *free_list;
     size_t unit_size;     /* size in bytes of an individual pool item */
     size_t units_per_alloc;
     size_t free_entries;    /* number of resources in the free pool */
-    size_t free_pool_size;  /* total number of slots in the free pool */
     size_t replenish_level; /* minimum free entries before replenishing
*/
     void (*replenish)(struct Parrot_Interp *, struct Resource_Pool *);
     struct Memory_Pool *mem_pool;



Reply via email to