[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