From 5b7cdcca8ce9389ccd138c69c72e769a3aea48a8 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Tue, 24 Feb 2009 03:35:32 +0100 Subject: Improve the boehm gc scheduler. --- .../patches/01-gc-include-private-gcconfig-h.patch | 7 +- .../boehm-gc/patches/05-viengoos-scheduler.patch | 145 +++++++++++++-------- 2 files changed, 93 insertions(+), 59 deletions(-) diff --git a/benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch b/benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch index ff3d1fc..f8a0a1e 100644 --- a/benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch +++ b/benchmarks/boehm-gc/patches/01-gc-include-private-gcconfig-h.patch @@ -4,8 +4,9 @@ exit $? Tweak the configuration. ---- gc.orig/include/private/gcconfig.h 2007-06-29 02:00:09.000000000 +0200 -+++ gc/include/private/gcconfig.h 2009-02-21 02:28:37.000000000 +0100 +diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in gc/include/private/gcconfig.h gc.new/include/private/gcconfig.h +--- gc/include/private/gcconfig.h 2007-06-29 02:00:09.000000000 +0200 ++++ gc.new/include/private/gcconfig.h 2009-02-23 22:59:56.000000000 +0100 @@ -451,7 +451,28 @@ # define HURD # define I386 @@ -32,7 +33,7 @@ Tweak the configuration. +# include +extern vg_addr_t gc_activity __attribute__ ((weak)); +# define ACTIVITY (&gc_activity ? gc_activity : VG_ADDR_VOID) -+extern int GC_available_bytes; ++extern uintptr_t GC_available_bytes; # endif # if defined(__TANDEM) /* Nonstop S-series */ diff --git a/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch b/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch index 2f3a389..a9361d5 100644 --- a/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch +++ b/benchmarks/boehm-gc/patches/05-viengoos-scheduler.patch @@ -6,9 +6,9 @@ Patch to support the Viengoos specific scheduler. To disable it, set GC_viengoos_scheduler to 0. -diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -rup gc.orig/allchblk.c gc/allchblk.c +diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in gc.orig/allchblk.c gc/allchblk.c --- gc.orig/allchblk.c 2007-06-07 02:40:07.000000000 +0200 -+++ gc/allchblk.c 2009-02-21 02:15:48.000000000 +0100 ++++ gc/allchblk.c 2009-02-24 03:07:28.000000000 +0100 @@ -117,7 +117,9 @@ void GC_print_hblkfreelist() while (h != 0) { hhdr = HDR(h); @@ -20,7 +20,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru total_free += sz; if (GC_is_black_listed(h, HBLKSIZE) != 0) { GC_printf("start black listed\n"); -@@ -381,31 +383,135 @@ void GC_add_to_fl(struct hblk *h, hdr *h +@@ -381,31 +383,142 @@ void GC_add_to_fl(struct hblk *h, hdr *h #ifdef USE_MUNMAP @@ -44,6 +44,8 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru - - for (i = 0; i <= N_HBLK_FLS; ++i) { + ++ uint64_t mapped_start = GC_get_heap_size() - GC_unmapped_bytes; ++ + start: + if (GC_viengoos_scheduler + && (GC_get_heap_size() - GC_unmapped_bytes @@ -51,12 +53,17 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru + /* The number of mapped bytes is at most 7/8s the available + memory. That's good enough for now. (Recall: the high-water + mark is 15/16s the available memory.) */ ++ uint64_t mapped_now = GC_get_heap_size() - GC_unmapped_bytes; ++ ++ extern char *program_name; + if (0) -+ printf ("%x: After unmapping %d used (%d available)\n", -+ l4_myself (), -+ (GC_get_heap_size() - GC_unmapped_bytes) / 4096, -+ GC_available_bytes / 4096); -+ return; ++ printf ("%s("VG_THREAD_ID_FMT"): After unmapping %"PRId64" mb, " ++ "%"PRId64"mb used (%"PRId64"mb available)\n", ++ program_name, hurd_myself (), ++ (mapped_start - mapped_now) / 1024 / 1024, ++ mapped_now / 1024 / 1024, ++ (uint64_t) GC_available_bytes / 1024 / 1024); ++ return; + } + + /* Start with the large blocks and work our way down. */ @@ -166,7 +173,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru } /* Merge all unmapped blocks that are adjacent to other free */ -@@ -413,6 +519,12 @@ void GC_unmap_old(void) +@@ -413,6 +526,12 @@ void GC_unmap_old(void) /* fully mapped or fully unmapped. */ void GC_merge_unmapped(void) { @@ -179,7 +186,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru struct hblk * h, *next; hdr * hhdr, *nexthdr; word size, nextsize; -@@ -600,12 +712,26 @@ GC_allochblk_nth(size_t sz, int kind, un +@@ -600,12 +719,26 @@ GC_allochblk_nth(size_t sz, int kind, un size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz); @@ -206,7 +213,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru if (size_avail != size_needed && !GC_use_entire_heap && !GC_dont_gc -@@ -642,7 +768,7 @@ GC_allochblk_nth(size_t sz, int kind, un +@@ -642,7 +775,7 @@ GC_allochblk_nth(size_t sz, int kind, un next_size = (signed_word)(thishdr -> hb_sz); if (next_size < size_avail && next_size >= size_needed @@ -215,7 +222,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru continue; } } -@@ -748,10 +874,12 @@ GC_allochblk_nth(size_t sz, int kind, un +@@ -748,10 +881,12 @@ GC_allochblk_nth(size_t sz, int kind, un /* hbp may be on the wrong freelist; the parameter n */ /* is important. */ hbp = GC_get_first_part(hbp, hhdr, size_needed, n); @@ -229,9 +236,9 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru if (0 == hbp) return 0; /* Add it to map of valid blocks */ -diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -rup gc/alloc.c gc.now/alloc.c ---- gc.orig/alloc.c 2007-06-22 04:40:30.000000000 +0200 -+++ gc/alloc.c 2009-02-22 03:15:24.000000000 +0100 +diff -urp -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in gc/alloc.c gc.new/alloc.c +--- gc/alloc.c 2007-06-22 04:40:30.000000000 +0200 ++++ gc.new/alloc.c 2009-02-24 03:07:16.000000000 +0100 @@ -15,6 +15,13 @@ * */ @@ -255,15 +262,15 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru /* * Separate free lists are maintained for different sized objects * up to MAXOBJBYTES. -@@ -223,9 +232,134 @@ void GC_clear_a_few_frames() +@@ -223,9 +232,160 @@ void GC_clear_a_few_frames() /* limits used by blacklisting. */ static word GC_collect_at_heapsize = (word)(-1); +int GC_viengoos_scheduler = 1; -+int GC_available_bytes = (256 + 128) * 1024 * 1024; ++uintptr_t GC_available_bytes = (uintptr_t) ((256 + 128) * 1024 * 1024); +int GC_could_unmap; + -+#define THRESHOLD (15 * (GC_available_bytes / 16)) ++#define THRESHOLD ((uintptr_t) (15 * (GC_available_bytes / 16))) + +#ifdef __gnu_hurd_viengoos__ +static void * @@ -281,16 +288,31 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru + period, &info); + assert_perror (err); + ++ /* What I think I've allocated. This it the amount of mapped ++ heap; it does not include pages tables, etc. */ ++ uint64_t my_alloced = GC_get_heap_size () - GC_unmapped_bytes; ++ /* What the kernel thinks I've allocated. It only includes ++ physical memory. */ ++ uint64_t real_alloced = (uint64_t) (info.stats.stats[0].dirty ++ + info.stats.stats[0].clean) ++ * PAGESIZE; ++ ++ uint64_t old_avail = GC_available_bytes; ++ + switch (info.event) + { + case vg_activity_info_stats: -+ GC_available_bytes = info.stats.stats[0].available_local * PAGESIZE; ++ GC_available_bytes ++ = (uintptr_t) info.stats.stats[0].available_local * PAGESIZE ++ - (real_alloced - my_alloced); + period = info.stats.stats[0].period + 1; + break; + + case vg_activity_info_pressure: -+ if (-info.pressure.amount * PAGESIZE < GC_available_bytes) -+ GC_available_bytes -= -info.pressure.amount * PAGESIZE; ++ /* PRESSURE.AMOUNT is negative. */ ++ if (-(uintptr_t) info.pressure.amount * PAGESIZE < my_alloced) ++ GC_available_bytes ++ = my_alloced + (uintptr_t) info.pressure.amount * PAGESIZE; + else + /* Huh? */ + GC_available_bytes = 0; @@ -300,21 +322,29 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru + panic ("Unknown event and unrequested event: %"PRIdPTR, info.event); + } + ++ extern char *program_name; + if (0) -+ printf (VG_THREAD_ID_FMT": %s: %d alloced: %d, heap: %d, " -+ "mapped:%d, unmapped: %d, available: %d, " -+ "low-water: %d\n", -+ hurd_myself (), ++ printf ("%s("VG_THREAD_ID_FMT"): %s: " ++ "%"PRId64" alloced: %"PRId64"mb, heap: %"PRId64"mb, " ++ "mapped:%"PRId64"mb, unmapped: %"PRId64"mb, " ++ "available: %"PRIdPTR"mb => %"PRIdPTR"mb, " ++ "low-water: %"PRIdPTR"mb\n", ++ program_name, hurd_myself (), + info.event == vg_activity_info_stats + ? "Period" : DEBUG_BOLD ("PRESSURE"), -+ (int) (info.event == vg_activity_info_stats -+ ? period : info.pressure.amount), -+ (int) GC_adj_bytes_allocd() / PAGESIZE, -+ (int) GC_get_heap_size () / PAGESIZE, -+ (int) (GC_get_heap_size () - GC_unmapped_bytes) / PAGESIZE, -+ (int) GC_unmapped_bytes / PAGESIZE, -+ (int) GC_available_bytes / PAGESIZE, -+ (int) THRESHOLD / PAGESIZE); ++ (uint64_t) (info.event == vg_activity_info_stats ++ ? period : info.pressure.amount), ++ (uint64_t) GC_adj_bytes_allocd() / 1024 / 1024, ++ (uint64_t) GC_get_heap_size () / 1024 / 1024, ++ (uint64_t) (GC_get_heap_size () - GC_unmapped_bytes) ++ / 1024 / 1024, ++ (uint64_t) GC_unmapped_bytes / 1024 / 1024, ++ (uint64_t) old_avail / 1024 / 1024, ++ (uint64_t) GC_available_bytes / 1024 / 1024, ++ (uint64_t) THRESHOLD / 1024 / 1024); ++ if (info.event == vg_activity_info_pressure) ++ printf ("pages to free: %d mb\n", ++ info.pressure.amount * (PAGESIZE / 1024) / 1024); + } +} +#endif @@ -369,18 +399,21 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru + a GC. */ + if (warning != GC_gc_no) { + warning = GC_gc_no; ++ extern char *program_name; + if (0) -+ printf ("Scheduling GC: (%u) alloced: %dkb, heap: %dkb, " -+ "mapped: %dkb, unmapped: %dkb, available: %dkb, " -+ "low-water: %dkb\n", -+ (int) GC_gc_no, -+ (int) alloced / 1024, -+ (int) GC_get_heap_size () / 1024, -+ (int) (GC_get_heap_size () - GC_unmapped_bytes) -+ / 1024, -+ (int) GC_unmapped_bytes / 1024, -+ (int) GC_available_bytes / 1024, -+ (int) THRESHOLD); ++ printf ("%s("VG_THREAD_ID_FMT"): Scheduling GC #%u: " ++ "alloced: %"PRId64"mb, heap: %"PRId64"mb, " ++ "mapped: %"PRId64"mb, unmapped: %"PRId64"mb, " ++ "available: %"PRIdPTR"mb, low-water: %"PRIdPTR"mb\n", ++ program_name, hurd_myself (), ++ (uint64_t) GC_gc_no, ++ (uint64_t) alloced / 1024 / 1024, ++ (uint64_t) GC_get_heap_size () / 1024 / 1024, ++ (uint64_t) (GC_get_heap_size () - GC_unmapped_bytes) ++ / 1024 / 1024, ++ (uint64_t) GC_unmapped_bytes / 1024 / 1024, ++ (uint64_t) GC_available_bytes / 1024 / 1024, ++ (uint64_t) THRESHOLD / 1024 / 1024); + } + } + @@ -390,7 +423,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru return(GC_adj_bytes_allocd() >= min_bytes_allocd() || GC_heapsize >= GC_collect_at_heapsize); } -@@ -256,6 +390,8 @@ void GC_maybe_gc(void) +@@ -256,6 +416,8 @@ void GC_maybe_gc(void) n_partial_gcs = 0; return; } else { @@ -399,7 +432,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru # ifdef PARALLEL_MARK GC_wait_for_reclaim(); # endif -@@ -266,6 +402,7 @@ void GC_maybe_gc(void) +@@ -266,6 +428,7 @@ void GC_maybe_gc(void) (unsigned long)GC_gc_no+1, (long)GC_bytes_allocd); } @@ -407,7 +440,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru GC_promote_black_lists(); (void)GC_reclaim_all((GC_stop_func)0, TRUE); GC_clear_marks(); -@@ -275,7 +412,11 @@ void GC_maybe_gc(void) +@@ -275,7 +438,11 @@ void GC_maybe_gc(void) } else { n_partial_gcs++; } @@ -419,7 +452,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru /* We try to mark with the world stopped. */ /* If we run out of time, this turns into */ /* incremental marking. */ -@@ -294,6 +435,8 @@ void GC_maybe_gc(void) +@@ -294,6 +461,8 @@ void GC_maybe_gc(void) GC_n_attempts++; } } @@ -428,7 +461,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru } } -@@ -325,6 +468,10 @@ GC_bool GC_try_to_collect_inner(GC_stop_ +@@ -325,6 +494,10 @@ GC_bool GC_try_to_collect_inner(GC_stop_ "Initiating full world-stop collection %lu after %ld allocd bytes\n", (unsigned long)GC_gc_no+1, (long)GC_bytes_allocd); } @@ -439,7 +472,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru GC_promote_black_lists(); /* Make sure all blocks have been reclaimed, so sweep routines */ /* don't see cleared mark bits. */ -@@ -337,7 +484,8 @@ GC_bool GC_try_to_collect_inner(GC_stop_ +@@ -337,7 +510,8 @@ GC_bool GC_try_to_collect_inner(GC_stop_ if ((GC_find_leak || stop_func != GC_never_stop_func) && !GC_reclaim_all(stop_func, FALSE)) { /* Aborted. So far everything is still consistent. */ @@ -449,7 +482,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru } GC_invalidate_mark_state(); /* Flush mark stack. */ GC_clear_marks(); -@@ -354,7 +502,8 @@ GC_bool GC_try_to_collect_inner(GC_stop_ +@@ -354,7 +528,8 @@ GC_bool GC_try_to_collect_inner(GC_stop_ GC_unpromote_black_lists(); } /* else we claim the world is already still consistent. We'll */ /* finish incrementally. */ @@ -459,7 +492,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru } GC_finish_collection(); if (GC_print_stats) { -@@ -362,7 +511,10 @@ GC_bool GC_try_to_collect_inner(GC_stop_ +@@ -362,7 +537,10 @@ GC_bool GC_try_to_collect_inner(GC_stop_ GC_log_printf("Complete collection took %lu msecs\n", MS_TIME_DIFF(current_time,start_time)); } @@ -471,7 +504,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru } -@@ -390,6 +542,8 @@ void GC_collect_a_little_inner(int n) +@@ -390,6 +568,8 @@ void GC_collect_a_little_inner(int n) if (GC_dont_gc) return; if (GC_incremental && GC_collection_in_progress()) { @@ -480,7 +513,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru for (i = GC_deficit; i < GC_RATE*n; i++) { if (GC_mark_some((ptr_t)0)) { /* Need to finish a collection */ -@@ -415,6 +569,8 @@ void GC_collect_a_little_inner(int n) +@@ -415,6 +595,8 @@ void GC_collect_a_little_inner(int n) } if (GC_deficit > 0) GC_deficit -= GC_RATE*n; if (GC_deficit < 0) GC_deficit = 0; @@ -489,7 +522,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru } else { GC_maybe_gc(); } -@@ -904,6 +1060,8 @@ GC_bool GC_expand_hp_inner(word n) +@@ -904,6 +1086,8 @@ GC_bool GC_expand_hp_inner(word n) /* Force GC before we are likely to allocate past expansion_slop */ GC_collect_at_heapsize = GC_heapsize + expansion_slop - 2*MAXHINCR*HBLKSIZE; @@ -498,7 +531,7 @@ diff -x config.guess -x config.sub -x 'aclocal*' -x configure -x Makefile.in -ru # if defined(LARGE_CONFIG) if (GC_collect_at_heapsize < GC_heapsize /* wrapped */) GC_collect_at_heapsize = (word)(-1); -@@ -1021,3 +1179,410 @@ ptr_t GC_allocobj(size_t gran, int kind) +@@ -1021,3 +1205,410 @@ ptr_t GC_allocobj(size_t gran, int kind) return(*flh); } -- cgit v1.2.3