[svn:parrot] r49344 - in branches/gc_ms2_tuning: include/parrot src/gc t/op

nwellnhof at svn.parrot.org nwellnhof at svn.parrot.org
Sun Sep 26 17:18:30 UTC 2010


Author: nwellnhof
Date: Sun Sep 26 17:18:29 2010
New Revision: 49344
URL: https://trac.parrot.org/parrot/changeset/49344

Log:
[gc] Add dynamic threshold to GC MS2

memory_used now also accounts for attribute and other fixed size storage
and ignores constant objects. The old code could lead to a lot more
memory being used than accounted for, so rather low thresholds could
still work very well. To address this, the default dynamic GC threshold
has been increased to 75%. Note that these changes have not been applied
to the old GC. It still uses the old accounting.

Also cleanup string compacting code.

Modified:
   branches/gc_ms2_tuning/include/parrot/gc_api.h
   branches/gc_ms2_tuning/src/gc/fixed_allocator.c
   branches/gc_ms2_tuning/src/gc/fixed_allocator.h
   branches/gc_ms2_tuning/src/gc/gc_ms.c
   branches/gc_ms2_tuning/src/gc/gc_ms2.c
   branches/gc_ms2_tuning/src/gc/gc_private.h
   branches/gc_ms2_tuning/src/gc/mark_sweep.c
   branches/gc_ms2_tuning/src/gc/string_gc.c
   branches/gc_ms2_tuning/t/op/gc-leaky-box.t
   branches/gc_ms2_tuning/t/op/gc-leaky-call.t
   branches/gc_ms2_tuning/t/op/gc-non-recursive.t

Modified: branches/gc_ms2_tuning/include/parrot/gc_api.h
==============================================================================
--- branches/gc_ms2_tuning/include/parrot/gc_api.h	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/include/parrot/gc_api.h	Sun Sep 26 17:18:29 2010	(r49344)
@@ -33,7 +33,7 @@
 
 #define ALIGNED_STRING_SIZE(len) (((len) + sizeof (void*) + WORD_ALIGN_1) & WORD_ALIGN_MASK)
 
-#define GC_DYNAMIC_THRESHOLD_DEFAULT 25
+#define GC_DYNAMIC_THRESHOLD_DEFAULT 75
 
 /* pool iteration */
 typedef enum {

Modified: branches/gc_ms2_tuning/src/gc/fixed_allocator.c
==============================================================================
--- branches/gc_ms2_tuning/src/gc/fixed_allocator.c	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/src/gc/fixed_allocator.c	Sun Sep 26 17:18:29 2010	(r49344)
@@ -18,14 +18,17 @@
 
 #include "parrot/parrot.h"
 #include "fixed_allocator.h"
+#include "gc_private.h"
 
 /* HEADERIZER HFILE: src/gc/fixed_allocator.h */
 
 /* HEADERIZER BEGIN: static */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 
-static void allocate_new_pool_arena(ARGMOD(Pool_Allocator *pool))
+static void allocate_new_pool_arena(PARROT_INTERP,
+    ARGMOD(Pool_Allocator *pool))
         __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
         FUNC_MODIFIES(*pool);
 
 static size_t arena_size(ARGIN(const Pool_Allocator *self))
@@ -42,12 +45,15 @@
         FUNC_MODIFIES(*pool);
 
 PARROT_CANNOT_RETURN_NULL
-static void * pool_allocate(ARGMOD(Pool_Allocator *pool))
+static void * pool_allocate(PARROT_INTERP, ARGMOD(Pool_Allocator *pool))
         __attribute__nonnull__(1)
+        __attribute__nonnull__(2)
         FUNC_MODIFIES(*pool);
 
-static void pool_free(ARGMOD(Pool_Allocator *pool), ARGFREE(void *data))
-        __attribute__nonnull__(1)
+static void pool_free(SHIM_INTERP,
+    ARGMOD(Pool_Allocator *pool),
+    ARGFREE(void *data))
+        __attribute__nonnull__(2)
         FUNC_MODIFIES(*pool);
 
 static int pool_is_owned(ARGMOD(Pool_Allocator *pool), ARGIN(void *ptr))
@@ -56,7 +62,8 @@
         FUNC_MODIFIES(*pool);
 
 #define ASSERT_ARGS_allocate_new_pool_arena __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(pool))
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_arena_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(self))
 #define ASSERT_ARGS_get_free_list_item __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
@@ -64,7 +71,8 @@
 #define ASSERT_ARGS_get_newfree_list_item __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_pool_allocate __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(pool))
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_pool_free __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_pool_is_owned __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
@@ -158,7 +166,7 @@
         allocator->pools[index] = Parrot_gc_pool_new(interp, alloc_size);
     }
 
-    ret = pool_allocate(allocator->pools[index]);
+    ret = pool_allocate(interp, allocator->pools[index]);
 
     /* memset ret to 0 here? */
     return ret;
@@ -178,7 +186,7 @@
 
     PARROT_ASSERT(allocator->pools[index]);
 
-    pool_free(allocator->pools[index], data);
+    pool_free(interp, allocator->pools[index], data);
 }
 
 /*
@@ -266,15 +274,15 @@
 Parrot_gc_pool_allocate(PARROT_INTERP, ARGMOD(Pool_Allocator * pool))
 {
     ASSERT_ARGS(Parrot_gc_pool_allocate)
-    return pool_allocate(pool);
+    return pool_allocate(interp, pool);
 }
 
 PARROT_EXPORT
 void
-Parrot_gc_pool_free(SHIM_INTERP, ARGMOD(Pool_Allocator *pool), ARGFREE(void *data))
+Parrot_gc_pool_free(PARROT_INTERP, ARGMOD(Pool_Allocator *pool), ARGFREE(void *data))
 {
     ASSERT_ARGS(Parrot_gc_pool_free)
-    pool_free(pool, data);
+    pool_free(interp, pool, data);
 }
 
 PARROT_EXPORT
@@ -292,13 +300,13 @@
 
 =over 4
 
-=item C<static void * pool_allocate(Pool_Allocator *pool)>
+=item C<static void * pool_allocate(PARROT_INTERP, Pool_Allocator *pool)>
 
 =item C<static void * get_free_list_item(Pool_Allocator *pool)>
 
 =item C<static void * get_newfree_list_item(Pool_Allocator *pool)>
 
-=item C<static void pool_free(Pool_Allocator *pool, void *data)>
+=item C<static void pool_free(PARROT_INTERP, Pool_Allocator *pool, void *data)>
 
 =item C<static int pool_is_owned(Pool_Allocator *pool, void *ptr)>
 
@@ -337,28 +345,27 @@
 
 PARROT_CANNOT_RETURN_NULL
 static void *
-pool_allocate(ARGMOD(Pool_Allocator *pool))
+pool_allocate(PARROT_INTERP, ARGMOD(Pool_Allocator *pool))
 {
     ASSERT_ARGS(pool_allocate)
-    Pool_Allocator_Free_List *item;
-
-    if (pool->free_list)
-        item = (Pool_Allocator_Free_List*)get_free_list_item(pool);
-
-    else if (pool->newfree)
-        item = (Pool_Allocator_Free_List*)get_newfree_list_item(pool);
+    void *item;
 
+    if (pool->free_list) {
+        item = get_free_list_item(pool);
+    }
     else {
-        allocate_new_pool_arena(pool);
-        item = (Pool_Allocator_Free_List*)get_newfree_list_item(pool);
+        if (!pool->newfree)
+            allocate_new_pool_arena(interp, pool);
+
+        item = get_newfree_list_item(pool);
     }
 
     --pool->num_free_objects;
-    return (void *)item;
+    return item;
 }
 
 static void
-pool_free(ARGMOD(Pool_Allocator *pool), ARGFREE(void *data))
+pool_free(SHIM_INTERP, ARGMOD(Pool_Allocator *pool), ARGFREE(void *data))
 {
     ASSERT_ARGS(pool_free)
     Pool_Allocator_Free_List * const item = (Pool_Allocator_Free_List *)data;
@@ -403,7 +410,8 @@
 
 /*
 
-=item C<static void allocate_new_pool_arena(Pool_Allocator *pool)>
+=item C<static void allocate_new_pool_arena(PARROT_INTERP, Pool_Allocator
+*pool)>
 
 Allocate a new pool arena
 
@@ -412,18 +420,25 @@
 */
 
 static void
-allocate_new_pool_arena(ARGMOD(Pool_Allocator *pool))
+allocate_new_pool_arena(PARROT_INTERP, ARGMOD(Pool_Allocator *pool))
 {
     ASSERT_ARGS(allocate_new_pool_arena)
     Pool_Allocator_Free_List *next;
+    Pool_Allocator_Arena     *new_arena;
 
     const size_t num_items  = pool->objects_per_alloc;
     const size_t item_size  = pool->object_size;
     const size_t item_space = item_size * num_items;
-
     /* Round up to 4kb */
-    Pool_Allocator_Arena * const new_arena = (Pool_Allocator_Arena *)mem_internal_allocate(
-                                                arena_size(pool));
+    const size_t total_size = arena_size(pool);
+
+    /* Run a GC if needed */
+    if (Parrot_gc_ms_needed(interp))
+        Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG);
+
+    new_arena = (Pool_Allocator_Arena *)mem_internal_allocate_zeroed(total_size);
+
+    interp->gc_sys->stats.memory_allocated += total_size;
 
     new_arena->prev = NULL;
     new_arena->next = pool->top_arena;
@@ -439,8 +454,8 @@
     if (pool->lo_arena_ptr > new_arena)
         pool->lo_arena_ptr = new_arena;
 
-    if (pool->hi_arena_ptr < (char*)new_arena + GC_FIXED_SIZE_POOL_SIZE)
-        pool->hi_arena_ptr = new_arena + GC_FIXED_SIZE_POOL_SIZE;
+    if (pool->hi_arena_ptr < (char*)new_arena + total_size)
+        pool->hi_arena_ptr = new_arena + total_size;
 }
 
 /*

Modified: branches/gc_ms2_tuning/src/gc/fixed_allocator.h
==============================================================================
--- branches/gc_ms2_tuning/src/gc/fixed_allocator.h	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/src/gc/fixed_allocator.h	Sun Sep 26 17:18:29 2010	(r49344)
@@ -99,9 +99,10 @@
         FUNC_MODIFIES(*pool);
 
 PARROT_EXPORT
-void Parrot_gc_pool_free(SHIM_INTERP,
+void Parrot_gc_pool_free(PARROT_INTERP,
     ARGMOD(Pool_Allocator *pool),
     ARGFREE(void *data))
+        __attribute__nonnull__(1)
         __attribute__nonnull__(2)
         FUNC_MODIFIES(*pool);
 
@@ -139,7 +140,8 @@
 #define ASSERT_ARGS_Parrot_gc_pool_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_Parrot_gc_pool_free __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(pool))
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(pool))
 #define ASSERT_ARGS_Parrot_gc_pool_is_owned __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(pool) \
     , PARROT_ASSERT_ARG(ptr))

Modified: branches/gc_ms2_tuning/src/gc/gc_ms.c
==============================================================================
--- branches/gc_ms2_tuning/src/gc/gc_ms.c	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/src/gc/gc_ms.c	Sun Sep 26 17:18:29 2010	(r49344)
@@ -621,10 +621,8 @@
 
     /* Note it */
     ++interp->gc_sys->stats.gc_mark_runs;
-    interp->gc_sys->stats.header_allocs_since_last_collect = 0;
 
     --mem_pools->gc_mark_block_level;
-    interp->gc_sys->stats.header_allocs_since_last_collect = 0;
     interp->gc_sys->stats.mem_used_last_collect = interp->gc_sys->stats.memory_used;
 
     return;

Modified: branches/gc_ms2_tuning/src/gc/gc_ms2.c
==============================================================================
--- branches/gc_ms2_tuning/src/gc/gc_ms2.c	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/src/gc/gc_ms2.c	Sun Sep 26 17:18:29 2010	(r49344)
@@ -39,9 +39,6 @@
     /* String GC */
     struct String_GC        string_gc;
 
-    /* Number of allocated objects before trigger gc */
-    size_t gc_threshold;
-
     /* GC blocking */
     UINTVAL gc_mark_block_level;  /* How many outstanding GC block
                                      requests are there? */
@@ -101,8 +98,7 @@
 
 PARROT_MALLOC
 PARROT_CAN_RETURN_NULL
-static STRING* gc_ms2_allocate_string_header(PARROT_INTERP,
-    SHIM(UINTVAL flags))
+static STRING* gc_ms2_allocate_string_header(PARROT_INTERP, UINTVAL flags)
         __attribute__nonnull__(1);
 
 static void gc_ms2_allocate_string_storage(PARROT_INTERP,
@@ -195,9 +191,6 @@
 static void gc_ms2_mark_pobj_header(PARROT_INTERP, ARGIN_NULLOK(PObj * obj))
         __attribute__nonnull__(1);
 
-static void gc_ms2_maybe_mark_and_sweep(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
 static void gc_ms2_pmc_needs_early_collection(PARROT_INTERP,
     ARGMOD(PMC *pmc))
         __attribute__nonnull__(1)
@@ -329,8 +322,6 @@
     , PARROT_ASSERT_ARG(pmc))
 #define ASSERT_ARGS_gc_ms2_mark_pobj_header __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp))
-#define ASSERT_ARGS_gc_ms2_maybe_mark_and_sweep __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
-       PARROT_ASSERT_ARG(interp))
 #define ASSERT_ARGS_gc_ms2_pmc_needs_early_collection \
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
@@ -455,7 +446,8 @@
                         self->fixed_size_allocator, attr_size);
     memset(PMC_data(pmc), 0, attr_size);
 
-    interp->gc_sys->stats.mem_used_last_collect += attr_size;
+    if (!PObj_constant_TEST(pmc))
+        interp->gc_sys->stats.memory_used += attr_size;
 
     return PMC_data(pmc);
 }
@@ -469,7 +461,8 @@
         Parrot_gc_fixed_allocator_free(interp, self->fixed_size_allocator,
                 PMC_data(pmc), pmc->vtable->attr_size);
 
-        interp->gc_sys->stats.mem_used_last_collect -= pmc->vtable->attr_size;
+        if (!PObj_constant_TEST(pmc))
+            interp->gc_sys->stats.memory_used -= pmc->vtable->attr_size;
     }
 }
 
@@ -480,8 +473,7 @@
     ASSERT_ARGS(gc_ms2_allocate_fixed_size_storage)
     MarkSweep_GC *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
 
-    interp->gc_sys->stats.memory_allocated      += size;
-    interp->gc_sys->stats.mem_used_last_collect += size;
+    interp->gc_sys->stats.memory_used += size;
 
     return Parrot_gc_fixed_allocator_allocate(interp, self->fixed_size_allocator, size);
 }
@@ -493,8 +485,7 @@
     if (data) {
         MarkSweep_GC *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
 
-        interp->gc_sys->stats.memory_allocated      -= size;
-        interp->gc_sys->stats.mem_used_last_collect -= size;
+        interp->gc_sys->stats.memory_used -= size;
 
         Parrot_gc_fixed_allocator_free(interp, self->fixed_size_allocator, data, size);
     }
@@ -620,10 +611,6 @@
         self->strings = Parrot_list_new(interp);
 
         self->fixed_size_allocator = Parrot_gc_fixed_allocator_new(interp);
-
-        /* Collect every 256M allocated. */
-        /* Hardcode for now. Will be configured via CLI */
-        self->gc_threshold = 256 * 1024 * 1024;
     }
     interp->gc_sys->gc_private = self;
 
@@ -662,12 +649,8 @@
     List_Item_Header *ptr;
     PMC              *ret;
 
-    gc_ms2_maybe_mark_and_sweep(interp);
-
-    /* Increase used memory. Not precisely accurate due Pool_Allocator paging */
-    ++interp->gc_sys->stats.header_allocs_since_last_collect;
-    interp->gc_sys->stats.memory_allocated      += sizeof (PMC);
-    interp->gc_sys->stats.mem_used_last_collect += sizeof (PMC);
+    if (!(flags & PObj_constant_FLAG))
+        interp->gc_sys->stats.memory_used += sizeof (PMC);
 
     ptr = (List_Item_Header *)Parrot_gc_pool_allocate(interp,
             self->pmc_allocator);
@@ -693,9 +676,8 @@
 
         Parrot_gc_pool_free(interp, self->pmc_allocator, Obj2LLH(pmc));
 
-        --interp->gc_sys->stats.header_allocs_since_last_collect;
-        interp->gc_sys->stats.memory_allocated      -= sizeof (PMC);
-        interp->gc_sys->stats.mem_used_last_collect -= sizeof (PMC);
+        if (!PObj_constant_TEST(pmc))
+            interp->gc_sys->stats.memory_used -= sizeof (PMC);
     }
 }
 
@@ -762,6 +744,7 @@
     ASSERT_ARGS(gc_ms2_sweep_pmc_cb)
     PMC *pmc = (PMC *)obj;
     Parrot_pmc_destroy(interp, pmc);
+    interp->gc_sys->stats.memory_used -= sizeof (PMC);
 }
 
 /*
@@ -782,19 +765,15 @@
 PARROT_MALLOC
 PARROT_CAN_RETURN_NULL
 static STRING*
-gc_ms2_allocate_string_header(PARROT_INTERP, SHIM(UINTVAL flags))
+gc_ms2_allocate_string_header(PARROT_INTERP, UINTVAL flags)
 {
     ASSERT_ARGS(gc_ms2_allocate_string_header)
     MarkSweep_GC     *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
     List_Item_Header *ptr;
     STRING           *ret;
 
-    gc_ms2_maybe_mark_and_sweep(interp);
-
-    /* Increase used memory. Not precisely accurate due Pool_Allocator paging */
-    ++interp->gc_sys->stats.header_allocs_since_last_collect;
-    interp->gc_sys->stats.memory_allocated      += sizeof (STRING);
-    interp->gc_sys->stats.mem_used_last_collect += sizeof (STRING);
+    if (!(flags & PObj_constant_FLAG))
+        interp->gc_sys->stats.memory_used += sizeof (STRING);
 
     ptr = (List_Item_Header *)Parrot_gc_pool_allocate(interp,
             self->string_allocator);
@@ -821,9 +800,8 @@
 
         Parrot_gc_pool_free(interp, self->string_allocator, Obj2LLH(s));
 
-        --interp->gc_sys->stats.header_allocs_since_last_collect;
-        interp->gc_sys->stats.memory_allocated      -= sizeof (STRING);
-        interp->gc_sys->stats.mem_used_last_collect -= sizeof (STRING);
+        if (!PObj_constant_TEST(s))
+            interp->gc_sys->stats.memory_used -= sizeof (STRING);
     }
 }
 
@@ -886,7 +864,6 @@
     ASSERT_ARGS(gc_ms2_allocate_string_storage)
     MarkSweep_GC *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
     Parrot_gc_str_allocate_string_storage(interp, &self->string_gc, str, size);
-    interp->gc_sys->stats.mem_used_last_collect += size;
 }
 
 static void
@@ -895,7 +872,6 @@
     ASSERT_ARGS(gc_ms2_reallocate_string_storage)
     MarkSweep_GC *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
     Parrot_gc_str_reallocate_string_storage(interp, &self->string_gc, str, size);
-    interp->gc_sys->stats.mem_used_last_collect += size;
 }
 
 static void
@@ -904,7 +880,6 @@
     ASSERT_ARGS(gc_ms2_allocate_buffer_storage)
     MarkSweep_GC *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
     Parrot_gc_str_allocate_buffer_storage(interp, &self->string_gc, str, size);
-    interp->gc_sys->stats.mem_used_last_collect += size;
 }
 
 static void
@@ -913,7 +888,6 @@
     ASSERT_ARGS(gc_ms2_reallocate_buffer_storage)
     MarkSweep_GC *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
     Parrot_gc_str_reallocate_buffer_storage(interp, &self->string_gc, str, size);
-    interp->gc_sys->stats.mem_used_last_collect += size;
 }
 
 /*
@@ -957,6 +931,7 @@
     /* Compact string pool here. Or get rid of "shared buffers" and just free storage */
     if (Buffer_bufstart(str) && !PObj_external_TEST(str))
         Parrot_gc_str_free_buffer_storage(interp, &self->string_gc, str);
+    interp->gc_sys->stats.memory_used -= sizeof (STRING);
 }
 
 
@@ -995,6 +970,7 @@
     MarkSweep_GC      *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
     List_Item_Header *tmp;
     Linked_List      *list;
+    GC_Statistics    *stats;
     size_t            counter;
     UNUSED(flags);
 
@@ -1007,11 +983,6 @@
         return;
     }
 
-    /* Ignore calls from String GC. We know better when to trigger GC */
-    if (flags & GC_strings_cb_FLAG) {
-        return;
-    }
-
     ++self->gc_mark_block_level;
 
     /* Allocate list for gray objects */
@@ -1057,14 +1028,15 @@
     self->objects = self->new_objects;
     Parrot_list_destroy(interp, list);
 
-    interp->gc_sys->stats.header_allocs_since_last_collect = 0;
-    interp->gc_sys->stats.mem_used_last_collect            = 0;
-    interp->gc_sys->stats.gc_mark_runs++;
+    gc_ms2_compact_memory_pool(interp);
+
+    stats = &interp->gc_sys->stats;
+    stats->mem_used_last_collect = stats->memory_used;
+    stats->gc_mark_runs++;
+
     self->gc_mark_block_level--;
     /* We swept all dead objects */
-    self->num_early_gc_PMCs                      = 0;
-
-    gc_ms2_compact_memory_pool(interp);
+    self->num_early_gc_PMCs = 0;
 }
 
 
@@ -1354,29 +1326,6 @@
 
 /*
 
-=item C<static void gc_ms2_maybe_mark_and_sweep(PARROT_INTERP)>
-
-Maybe M&S. Depends on total allocated memory, memory allocated since last alloc
-and phase of the Moon.
-
-=cut
-
-*/
-static void
-gc_ms2_maybe_mark_and_sweep(PARROT_INTERP)
-{
-    ASSERT_ARGS(gc_ms2_maybe_mark_and_sweep)
-
-    MarkSweep_GC *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
-
-    /* Collect every 256M. Hardcode for now. Will be configured via CLI */
-    if (interp->gc_sys->stats.mem_used_last_collect > self->gc_threshold) {
-        gc_ms2_mark_and_sweep(interp, 0);
-    }
-}
-
-/*
-
 =item C<static size_t gc_ms2_count_used_string_memory(PARROT_INTERP, Linked_List
 *list)>
 

Modified: branches/gc_ms2_tuning/src/gc/gc_private.h
==============================================================================
--- branches/gc_ms2_tuning/src/gc/gc_private.h	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/src/gc/gc_private.h	Sun Sep 26 17:18:29 2010	(r49344)
@@ -103,11 +103,13 @@
     size_t  mem_allocs_since_last_collect;      /* The number of memory
                                                  * allocations from the
                                                  * system since the last
-                                                 * compaction run */
+                                                 * compaction run.
+                                                 * UNUSED, ALWAYS 0 */
     size_t  header_allocs_since_last_collect;   /* The size of header
                                                  * blocks allocated from
                                                  * the system since the last
-                                                 * GC run */
+                                                 * GC run.
+                                                 * UNUSED, ALWAYS 0 */
     size_t  memory_allocated;     /* The total amount of memory allocated
                                    * in fixed and variable size pools.
                                    * Doesn't count memory for internal

Modified: branches/gc_ms2_tuning/src/gc/mark_sweep.c
==============================================================================
--- branches/gc_ms2_tuning/src/gc/mark_sweep.c	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/src/gc/mark_sweep.c	Sun Sep 26 17:18:29 2010	(r49344)
@@ -481,7 +481,6 @@
         new_arena->prev->next = new_arena;
 
     pool->last_Arena = new_arena;
-    interp->gc_sys->stats.header_allocs_since_last_collect += size;
     interp->gc_sys->stats.memory_allocated += size;
 }
 

Modified: branches/gc_ms2_tuning/src/gc/string_gc.c
==============================================================================
--- branches/gc_ms2_tuning/src/gc/string_gc.c	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/src/gc/string_gc.c	Sun Sep 26 17:18:29 2010	(r49344)
@@ -32,11 +32,6 @@
 #define RECLAMATION_FACTOR 0.20
 #define WE_WANT_EVER_GROWING_ALLOCATIONS 0
 
-typedef struct string_callback_data {
-    Memory_Block *new_block;     /* A pointer to our working block */
-    char         *cur_spot;      /* Where we're currently copying to */
-} string_callback_data;
-
 /* HEADERIZER HFILE: src/gc/gc_private.h */
 
 /* HEADERIZER BEGIN: static */
@@ -112,18 +107,13 @@
         __attribute__nonnull__(2)
         __attribute__nonnull__(3);
 
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static char * move_one_buffer(PARROT_INTERP,
+static void move_one_buffer(PARROT_INTERP,
     ARGIN(Memory_Block *pool),
-    ARGMOD(Buffer *old_buf),
-    ARGMOD(char *new_pool_ptr))
+    ARGMOD(Buffer *old_buf))
         __attribute__nonnull__(1)
         __attribute__nonnull__(2)
         __attribute__nonnull__(3)
-        __attribute__nonnull__(4)
-        FUNC_MODIFIES(*old_buf)
-        FUNC_MODIFIES(*new_pool_ptr);
+        FUNC_MODIFIES(*old_buf);
 
 PARROT_WARN_UNUSED_RESULT
 PARROT_MALLOC
@@ -170,8 +160,7 @@
 #define ASSERT_ARGS_move_one_buffer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(pool) \
-    , PARROT_ASSERT_ARG(old_buf) \
-    , PARROT_ASSERT_ARG(new_pool_ptr))
+    , PARROT_ASSERT_ARG(old_buf))
 #define ASSERT_ARGS_new_memory_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 #define ASSERT_ARGS_pad_pool_size __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(pool))
@@ -247,6 +236,8 @@
     ASSERT_ARGS(Parrot_gc_str_allocate_buffer_storage)
     const size_t new_size   = ALIGNED_STRING_SIZE(size);
 
+    interp->gc_sys->stats.memory_used += new_size;
+
     Buffer_bufstart(buffer) = (void *)aligned_mem(buffer,
         (char *)mem_allocate(interp,
         &interp->gc_sys->stats, new_size, gc->memory_pool));
@@ -279,10 +270,9 @@
         size_t newsize)
 {
     ASSERT_ARGS(Parrot_gc_str_reallocate_buffer_storage)
-    size_t copysize;
-    char  *mem;
     Variable_Size_Pool * const pool = gc->memory_pool;
-    size_t new_size, needed, old_size;
+    char   *mem;
+    size_t  new_size, old_size, copysize;
 
     /* we don't shrink buffers */
     if (newsize <= Buffer_buflen(buffer))
@@ -298,32 +288,21 @@
      */
     new_size = ALIGNED_STRING_SIZE(newsize);
     old_size = ALIGNED_STRING_SIZE(Buffer_buflen(buffer));
-    needed   = new_size - old_size;
-
-    if ((pool->top_block->free >= needed)
-    &&  (pool->top_block->top  == (char *)Buffer_bufstart(buffer) + old_size)) {
-        pool->top_block->free -= needed;
-        pool->top_block->top  += needed;
-        interp->gc_sys->stats.memory_used += needed;
-        Buffer_buflen(buffer)  = newsize;
-        return;
-    }
 
-    copysize = Buffer_buflen(buffer);
+    interp->gc_sys->stats.memory_used += new_size;
 
     mem = (char *)mem_allocate(interp, &interp->gc_sys->stats, new_size, pool);
     mem = aligned_mem(buffer, mem);
 
     /* We shouldn't ever have a 0 from size, but we do. If we can track down
      * those bugs, this can be removed which would make things cheaper */
+    copysize = Buffer_buflen(buffer);
+
     if (copysize)
         memcpy(mem, Buffer_bufstart(buffer), copysize);
 
     Buffer_bufstart(buffer) = mem;
-
-    new_size -= sizeof (void *);
-
-    Buffer_buflen(buffer) = new_size;
+    Buffer_buflen(buffer)   = new_size - sizeof (void *);
 
     /* Save pool used to allocate into buffer header */
     *Buffer_poolptr(buffer) = gc->memory_pool->top_block;
@@ -350,21 +329,26 @@
         size_t size)
 {
     ASSERT_ARGS(Parrot_gc_str_allocate_string_storage)
-    size_t       new_size;
     Variable_Size_Pool *pool;
-    char        *mem;
+    size_t  new_size;
+    char   *mem;
 
-    Buffer_buflen(str)   = 0;
-    Buffer_bufstart(str) = NULL;
-
-    if (size == 0)
+    if (size == 0) {
+        Buffer_buflen(str)   = 0;
+        Buffer_bufstart(str) = NULL;
         return;
-
-    pool     = PObj_constant_TEST(str)
-                ? gc->constant_string_pool
-                : gc->memory_pool;
+    }
 
     new_size = ALIGNED_STRING_SIZE(size);
+
+    if (PObj_constant_TEST(str)) {
+        pool = gc->constant_string_pool;
+    }
+    else {
+        pool = gc->memory_pool;
+        interp->gc_sys->stats.memory_used += new_size;
+    }
+
     mem      = (char *)mem_allocate(interp, &interp->gc_sys->stats, new_size, pool);
     mem     += sizeof (void *);
 
@@ -395,41 +379,24 @@
         size_t newsize)
 {
     ASSERT_ARGS(Parrot_gc_str_reallocate_string_storage)
-    size_t copysize;
-    char *mem, *oldmem;
-    size_t new_size, needed, old_size;
-
-    Variable_Size_Pool * const pool =
-        PObj_constant_TEST(str)
-            ? gc->constant_string_pool
-            : gc->memory_pool;
+    Variable_Size_Pool *pool;
+    char   *mem;
+    size_t  new_size, old_size;
 
     /* if the requested size is smaller then buflen, we are done */
     if (newsize <= Buffer_buflen(str))
         return;
 
-    /*
-     * first check, if we can reallocate:
-     * - if the passed strings buffer is the last string in the pool and
-     * - if there is enough size, we can just move the pool's top pointer
-     */
     new_size = ALIGNED_STRING_SIZE(newsize);
     old_size = ALIGNED_STRING_SIZE(Buffer_buflen(str));
-    needed   = new_size - old_size;
 
-    if (pool->top_block->free >= needed
-    &&  pool->top_block->top  == (char *)Buffer_bufstart(str) + old_size) {
-        pool->top_block->free -= needed;
-        pool->top_block->top  += needed;
-        interp->gc_sys->stats.memory_used += needed;
-        Buffer_buflen(str) = new_size - sizeof (void *);
-        return;
+    if (PObj_constant_TEST(str)) {
+        pool = gc->constant_string_pool;
+    }
+    else {
+        pool = gc->memory_pool;
+        interp->gc_sys->stats.memory_used += new_size;
     }
-
-    PARROT_ASSERT(str->bufused <= newsize);
-
-    /* only copy used memory, not total string buffer */
-    copysize = str->bufused;
 
     mem = (char *)mem_allocate(interp, &interp->gc_sys->stats, new_size, pool);
     mem += sizeof (void *);
@@ -445,16 +412,17 @@
     PARROT_ASSERT(Buffer_pool(str));
     Buffer_pool(str)->freed += old_size;
 
-    /* copy mem from strstart, *not* bufstart */
-    oldmem             = str->strstart;
-    Buffer_bufstart(str) = (void *)mem;
-    str->strstart      = mem;
-    Buffer_buflen(str)   = new_size - sizeof (void *);
+    PARROT_ASSERT(str->bufused <= Buffer_buflen(str));
 
+    /* copy mem from strstart, *not* bufstart */
+    /* only copy used memory, not total string buffer */
     /* We shouldn't ever have a 0 from size, but we do. If we can track down
      * those bugs, this can be removed which would make things cheaper */
-    if (copysize)
-        memcpy(mem, oldmem, copysize);
+    if (str->bufused)
+        memcpy(mem, str->strstart, str->bufused);
+
+    Buffer_bufstart(str) = str->strstart = mem;
+    Buffer_buflen(str)   = new_size - sizeof (void *);
 
     /* Save pool used to allocate into buffer header */
     *Buffer_poolptr(str) = pool->top_block;
@@ -655,28 +623,10 @@
 
     /* If not enough room, try to find some */
     if (pool->top_block->free < size) {
-        /*
-         * force a GC mark run to get live flags set
-         * for incremental M&S collection is run from there
-         * but only if there may be something worth collecting!
-         * TODO pass required allocation size to the GC system,
-         *      so that collection can be skipped if needed
-         */
-        if (!Parrot_is_blocked_GC_mark(interp)
-        &&  Parrot_gc_ms_needed(interp)) {
-            Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG | GC_strings_cb_FLAG);
-
-            if (interp->gc_sys->sys_type != INF) {
-                /* Compact the pool if allowed and worthwhile */
-                if (pool->compact) {
-                    /* don't bother reclaiming if it's only a small amount */
-                    if ((pool->possibly_reclaimable * pool->reclaim_factor +
-                         pool->guaranteed_reclaimable) > size) {
-                        (*pool->compact) (interp, stats, pool);
-                    }
-                }
-            }
-        }
+        /* Run a GC if needed */
+        if (Parrot_gc_ms_needed(interp))
+            Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG);
+
         if (pool->top_block->free < size) {
             if (pool->minimum_block_size < 65536 * 16)
                 pool->minimum_block_size *= 2;
@@ -686,9 +636,7 @@
              * Mark the block as big block (it has just one item)
              * And don't set big blocks as the top_block.
              */
-            alloc_new_block(&interp->gc_sys->stats, size, pool, "compact failed");
-
-            ++interp->gc_sys->stats.mem_allocs_since_last_collect;
+            alloc_new_block(stats, size, pool, "compact failed");
 
             if (pool->top_block->free < size) {
                 fprintf(stderr, "out of mem\n");
@@ -701,7 +649,6 @@
     return_val             = pool->top_block->top;
     pool->top_block->top  += size;
     pool->top_block->free -= size;
-    interp->gc_sys->stats.memory_used += size;
 
     return return_val;
 }
@@ -809,14 +756,11 @@
 {
     ASSERT_ARGS(compact_pool)
     INTVAL        j;
-    UINTVAL       total_size;
+    UINTVAL       total_size, new_size;
+    Memory_Block *new_block;
 
     Fixed_Size_Arena *cur_buffer_arena;
 
-    /* Contains new_block and cur_spot */
-    string_callback_data cb_data;
-
-
     /* Bail if we're blocked */
     if (Parrot_is_blocked_GC_sweep(interp))
         return;
@@ -824,8 +768,6 @@
     Parrot_block_GC_sweep(interp);
 
     /* We're collecting */
-    stats->mem_allocs_since_last_collect    = 0;
-    stats->header_allocs_since_last_collect = 0;
     ++stats->gc_collect_runs;
 
     /* Snag a block big enough for everything */
@@ -838,30 +780,22 @@
     }
 
     alloc_new_block(stats, total_size, pool, "inside compact");
-
-    cb_data.new_block = pool->top_block;
-
-    /* Start at the beginning */
-    cb_data.cur_spot  = cb_data.new_block->start;
+    new_block = pool->top_block;
 
     /* Run through all the Buffer header pools and copy */
-    interp->gc_sys->iterate_live_strings(interp, move_buffer_callback, &cb_data);
+    interp->gc_sys->iterate_live_strings(interp, move_buffer_callback, new_block);
+
+    new_size = new_block->top - new_block->start;
 
-    /* Okay, we're done with the copy. Set the bits in the pool struct */
-    /* First, where we allocate next */
-    cb_data.new_block->top = cb_data.cur_spot;
-
-    PARROT_ASSERT(cb_data.new_block->size
-                  >=
-                  (size_t)cb_data.new_block->top - (size_t)cb_data.new_block->start);
+    PARROT_ASSERT(new_block->size >= new_size);
 
     /* How much is free. That's the total size minus the amount we used */
-    cb_data.new_block->free     = cb_data.new_block->size
-                                  - (cb_data.cur_spot - cb_data.new_block->start);
-    stats->memory_collected += (cb_data.cur_spot - cb_data.new_block->start);
-    stats->memory_used      += (cb_data.cur_spot - cb_data.new_block->start);
+    new_block->free          = new_block->size - new_size;
 
-    free_old_mem_blocks(stats, pool, cb_data.new_block, total_size);
+    stats->memory_collected += new_size;
+    stats->memory_used      += new_size;
+
+    free_old_mem_blocks(stats, pool, new_block, total_size);
 
     Parrot_unblock_GC_sweep(interp);
 }
@@ -877,13 +811,13 @@
 move_buffer_callback(PARROT_INTERP, ARGIN(Buffer *b), ARGIN(void *data))
 {
     ASSERT_ARGS(move_buffer_callback)
-    string_callback_data *cb = (string_callback_data*)data;
+    Memory_Block *new_block = (Memory_Block *)data;
 
     if (Buffer_buflen(b) && PObj_is_movable_TESTALL(b)) {
         Memory_Block *old_block = Buffer_pool(b);
 
         if (!is_block_almost_full(old_block))
-            cb->cur_spot = move_one_buffer(interp, cb->new_block, b, cb->cur_spot);
+            move_one_buffer(interp, new_block, b);
     }
 
 }
@@ -960,8 +894,8 @@
 
 /*
 
-=item C<static char * move_one_buffer(PARROT_INTERP, Memory_Block *pool, Buffer
-*old_buf, char *new_pool_ptr)>
+=item C<static void move_one_buffer(PARROT_INTERP, Memory_Block *pool, Buffer
+*old_buf)>
 
 The compact_pool operation collects disjointed blocks of memory allocated on a
 given pool's free list into one large block of memory. Once the new larger
@@ -972,17 +906,14 @@
 
 */
 
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static char *
+static void
 move_one_buffer(PARROT_INTERP, ARGIN(Memory_Block *pool),
-        ARGMOD(Buffer *old_buf), ARGMOD(char *new_pool_ptr))
+        ARGMOD(Buffer *old_buf))
 {
     ASSERT_ARGS(move_one_buffer)
 
     INTVAL       *flags     = NULL;
     ptrdiff_t     offset    = 0;
-    Memory_Block *old_block = NULL;
 #if RESOURCE_DEBUG
     if (Buffer_buflen(old_buf) >= RESOURCE_DEBUG_SIZE)
         debug_print_buf(interp, old_buf);
@@ -994,11 +925,10 @@
         * strstart might be in unallocated memory */
     if (PObj_is_COWable_TEST(old_buf)) {
         flags = Buffer_bufflagsptr(old_buf);
-        old_block = Buffer_pool(old_buf);
 
         if (PObj_is_string_TEST(old_buf)) {
-            offset = (ptrdiff_t)((STRING *)old_buf)->strstart -
-                (ptrdiff_t)Buffer_bufstart(old_buf);
+            offset = ((STRING *)old_buf)->strstart -
+                (char *)Buffer_bufstart(old_buf);
         }
     }
 
@@ -1016,20 +946,12 @@
 
         /* Now make sure we point to where the other guy does */
         Buffer_bufstart(old_buf) = Buffer_bufstart(hdr);
-
-        /* And if we're a string, update strstart */
-        /* Somewhat of a hack, but if we get per-pool
-            * collections, it should help ease the pain */
-        if (PObj_is_string_TEST(old_buf))
-            ((STRING *)old_buf)->strstart =
-                (char *)Buffer_bufstart(old_buf) + offset;
     }
     else {
-        new_pool_ptr = aligned_mem(old_buf, new_pool_ptr);
+        char *new_pool_ptr = aligned_mem(old_buf, pool->top);
 
         /* Copy our memory to the new pool */
-        memcpy(new_pool_ptr, Buffer_bufstart(old_buf),
-                                Buffer_buflen(old_buf));
+        memcpy(new_pool_ptr, Buffer_bufstart(old_buf), Buffer_buflen(old_buf));
 
         /* If we're shared */
         if (flags && (*flags & Buffer_shared_FLAG)) {
@@ -1049,14 +971,14 @@
         /* Remember new pool inside */
         *Buffer_poolptr(old_buf) = pool;
 
-        if (PObj_is_string_TEST(old_buf))
-            ((STRING *)old_buf)->strstart =
-                    (char *)Buffer_bufstart(old_buf) + offset;
-
-        new_pool_ptr += Buffer_buflen(old_buf);
+        pool->top = new_pool_ptr + Buffer_buflen(old_buf);
     }
 
-    return new_pool_ptr;
+    /* And if we're a string, update strstart */
+    /* Somewhat of a hack */
+    if (PObj_is_string_TEST(old_buf))
+        ((STRING *)old_buf)->strstart =
+            (char *)Buffer_bufstart(old_buf) + offset;
 }
 
 /*
@@ -1100,7 +1022,7 @@
         else {
             /* Note that we don't have it any more */
             stats->memory_allocated -= cur_block->size;
-            stats->memory_used -= cur_block->size - cur_block->free;
+            stats->memory_used      -= cur_block->size - cur_block->free;
 
             /* We know the pool body and pool header are a single chunk, so
              * this is enough to get rid of 'em both */

Modified: branches/gc_ms2_tuning/t/op/gc-leaky-box.t
==============================================================================
--- branches/gc_ms2_tuning/t/op/gc-leaky-box.t	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/t/op/gc-leaky-box.t	Sun Sep 26 17:18:29 2010	(r49344)
@@ -27,7 +27,7 @@
 
 
     $S0 = interpinfo .INTERPINFO_GC_SYS_NAME
-    if $S0 != "ms" goto dont_run_hanging_tests
+    if $S0 == "inf" goto dont_run_hanging_tests
 
     plan(3)
     test_gc_mark_sweep()
@@ -63,8 +63,8 @@
 
     $S1 = $I3
     $S0 = "allocated " . $S1
-    $S0 .= " (which should be <= 2_000_000) bytes of memory"
-    $I4 = isle $I3, 2000000
+    $S0 .= " (which should be <= 4_000_000) bytes of memory"
+    $I4 = isle $I3, 4000000
     ok($I4,$S0)
 .end
 

Modified: branches/gc_ms2_tuning/t/op/gc-leaky-call.t
==============================================================================
--- branches/gc_ms2_tuning/t/op/gc-leaky-call.t	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/t/op/gc-leaky-call.t	Sun Sep 26 17:18:29 2010	(r49344)
@@ -24,7 +24,7 @@
 
 
     $S0 = interpinfo .INTERPINFO_GC_SYS_NAME
-    if $S0 != "ms" goto dont_run_hanging_tests
+    if $S0 == "inf" goto dont_run_hanging_tests
 
     plan(3)
     test_gc_mark_sweep()
@@ -60,8 +60,8 @@
 
     $S1 = $I3
     $S0 = "allocated " . $S1
-    $S0 .= " (which should be <= 2_000_000) bytes of memory"
-    $I4 = isle $I3, 2000000
+    $S0 .= " (which should be <= 4_000_000) bytes of memory"
+    $I4 = isle $I3, 4000000
     ok($I4,$S0)
 .end
 

Modified: branches/gc_ms2_tuning/t/op/gc-non-recursive.t
==============================================================================
--- branches/gc_ms2_tuning/t/op/gc-non-recursive.t	Sun Sep 26 17:06:51 2010	(r49343)
+++ branches/gc_ms2_tuning/t/op/gc-non-recursive.t	Sun Sep 26 17:18:29 2010	(r49344)
@@ -35,7 +35,7 @@
     next = head
   loop:
     ($I0, next) = next.'reify'()
-    if $I1 < 10000000 goto loop
+    if $I0 < 200000 goto loop
     sweep 1
     ok(1, "Marking of large list doesn't exhaust C stack")
     done_testing()


More information about the parrot-commits mailing list