[m-rev.] for review: boehm gc unmap capability

Peter Wang novalazy at gmail.com
Tue Jan 22 12:18:41 AEDT 2008


Estimated hours taken: 6
Branches: main

Allow the use of munmap() in Boehm GC, in order to return unused memory pages
back to the OS.  This has an adverse effect on run times so we want to be able
to enable it on a per-application basis.  To avoid installing both
munmap-enabled and munmap-disabled copies of Boehm GC, we make it so that
munmap() capability can be compiled in but disabled with a global variable.
In that case the performance difference (seems to) be negligible.

As mmap/munmap aren't supported on all platforms, munmap() capability needs to
be selected with `configure'.  It is currently disabled by default.

Mmake.common.in:
configure.in:
	Add the configure option `--enable-gc-munmap' and
	add -DUSE_MMAP -DUSE_MUNMAP to the Boehm GC C flags if set.

boehm_gc/allchblk.c:
boehm_gc/alloc.c:
boehm_gc/malloc.c:
boehm_gc/include/gc.h:
boehm_gc/include/private/gc_priv.h:
	Add the global variable `GC_mercury_use_munmap'.

	Modify the code to check `GC_mercury_use_munmap' before executing code
	that would normally be run when USE_MUNMAP is set.

runtime/mercury_wrapper.c:
	Set `GC_mercury_use_munmap' if MERCURY_OPTIONS contains `--munmap'.

doc/user_guide.texi:
	Document the new MERCURY_OPTIONS and configure options.


----------

This is as simple as I could make the boehm_gc changes.  Here are
timings on neptune:

MERCURY_OPTIONS=

    EXTRA_MCFLAGS = 
    # modified boehm_gc
    mercury_compile.01 average of 6 with ignore=1     23.67

    EXTRA_MCFLAGS = 
    BOEHM_CFLAGS += -DUSE_MMAP
    mercury_compile.02 average of 6 with ignore=1     24.24

    EXTRA_MCFLAGS = 
    BOEHM_CFLAGS += -DUSE_MMAP -DUSE_MUNMAP
    mercury_compile.03 average of 6 with ignore=1     23.73

    EXTRA_MCFLAGS = 
    # unmodified boehm_gc
    mercury_compile.04 average of 6 with ignore=1     23.60

MERCURY_OPTIONS=--munmap

    EXTRA_MCFLAGS = 
    # modified boehm_gc
    mercury_compile.01 average of 6 with ignore=1     23.69

    EXTRA_MCFLAGS = 
    BOEHM_CFLAGS += -DUSE_MMAP
    mercury_compile.02 average of 6 with ignore=1     24.00

    EXTRA_MCFLAGS = 
    BOEHM_CFLAGS += -DUSE_MMAP -DUSE_MUNMAP
    mercury_compile.03 average of 6 with ignore=1     28.13

    EXTRA_MCFLAGS = 
    # unmodified boehm_gc
    mercury_compile.04 average of 6 with ignore=1     23.66



Index: Mmake.common.in
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/Mmake.common.in,v
retrieving revision 1.94
diff -u -r1.94 Mmake.common.in
--- Mmake.common.in	4 Oct 2007 02:46:48 -0000	1.94
+++ Mmake.common.in	22 Jan 2008 00:36:52 -0000
@@ -144,7 +144,7 @@
 # MCFLAGS	+= --no-infer-all --halt-at-warn --no-warn-inferred-erroneous
 
 # Options to pass to the C compiler when building Boehm-GC.
-BOEHM_CFLAGS = @ENABLE_BOEHM_LARGE_CONFIG@
+BOEHM_CFLAGS = @ENABLE_BOEHM_LARGE_CONFIG@ @ENABLE_BOEHM_USE_MUNMAP@
 
 # Additional options to pass to the C compiler when building Boehm-GC for
 # threads.
Index: configure.in
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/configure.in,v
retrieving revision 1.512
diff -u -r1.512 configure.in
--- configure.in	17 Jan 2008 00:17:19 -0000	1.512
+++ configure.in	22 Jan 2008 00:36:52 -0000
@@ -437,6 +437,35 @@
 
 #-----------------------------------------------------------------------------#
 #
+# Determine whether to define USE_MUNMAP when compiling boehm_gc.
+#
+
+AC_ARG_ENABLE(gc-munmap,
+    AC_HELP_STRING([--enable-gc-munmap],
+                   [enable unmapping of unused pages when using Boehm GC]),
+    enable_gc_munmap="$enableval",enable_gc_munmap=no)
+
+AC_MSG_CHECKING(whether to enable unmapping of unused pages when using Boehm GC)
+case "$enable_gc_munmap" in
+	yes)
+		AC_MSG_RESULT(yes)
+		# USE_MUNMAP requires USE_MMAP.
+		ENABLE_BOEHM_USE_MUNMAP="-DUSE_MMAP -DUSE_MUNMAP"
+		;;
+	no)
+		AC_MSG_RESULT(no)
+		ENABLE_BOEHM_USE_MUNMAP=
+		;;
+	*)
+		AC_MSG_RESULT(no)
+		AC_MSG_WARN([unexpected argument to --enable-gc-munmap])
+		ENABLE_BOEHM_USE_MUNMAP=
+		;;
+esac
+AC_SUBST(ENABLE_BOEHM_USE_MUNMAP)
+
+#-----------------------------------------------------------------------------#
+#
 # Find the GCC source code
 # and determine whether or not to enable the GCC back-end interface.
 #
Index: boehm_gc/allchblk.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/boehm_gc/allchblk.c,v
retrieving revision 1.16
diff -u -r1.16 allchblk.c
--- boehm_gc/allchblk.c	15 Aug 2006 04:19:23 -0000	1.16
+++ boehm_gc/allchblk.c	22 Jan 2008 00:36:52 -0000
@@ -20,6 +20,11 @@
 
 GC_bool GC_use_entire_heap = 0;
 
+/* For Mercury: this is a hack to control use of munmap() when		*/
+/* USE_MUNMAP is enabled. Use GC_MERCURY_USE_MUNMAP when checking       */
+/* the value of this variable.						*/
+GC_bool GC_mercury_use_munmap = 0;
+
 /*
  * Free heap blocks are kept on one of several free lists,
  * depending on the size of the block.  Each free list is doubly linked.
@@ -46,7 +51,7 @@
 
 struct hblk * GC_hblkfreelist[N_HBLK_FLS+1] = { 0 };
 
-#ifndef USE_MUNMAP
+#if !defined(USE_MUNMAP) || 1 /* GC_MERCURY_USE_MUNMAP */
 
   word GC_free_bytes[N_HBLK_FLS+1] = { 0 };
 	/* Number of free bytes on each list.	*/
@@ -68,7 +73,10 @@
     return FALSE;
   }
 
-# define INCR_FREE_BYTES(n, b) GC_free_bytes[n] += (b);
+# define INCR_FREE_BYTES(n, b)                           \
+  do {                                                   \
+    if (!GC_MERCURY_USE_MUNMAP) GC_free_bytes[n] += (b); \
+  } while (0)
 
 # define FREE_ASSERT(e) GC_ASSERT(e)
 
@@ -94,7 +102,7 @@
 # define NHDR(hhdr) HDR(hhdr -> hb_next)
 
 # ifdef USE_MUNMAP
-#   define IS_MAPPED(hhdr) (((hhdr) -> hb_flags & WAS_UNMAPPED) == 0)
+#   define IS_MAPPED(hhdr) (!GC_MERCURY_USE_MUNMAP || (((hhdr) -> hb_flags & WAS_UNMAPPED) == 0))
 # else  /* !USE_MMAP */
 #   define IS_MAPPED(hhdr) 1
 # endif /* USE_MUNMAP */
@@ -292,21 +300,25 @@
     int index;
 
     GC_ASSERT(((hhdr -> hb_sz) & (HBLKSIZE-1)) == 0);
-#   ifndef USE_MUNMAP
+#   if !defined(USE_MUNMAP) || 1 /* GC_MERCURY_USE_MUNMAP */
+    if (!GC_MERCURY_USE_MUNMAP) {
       /* We always need index to mainatin free counts.	*/
       if (FL_UNKNOWN == n) {
           index = GC_hblk_fl_from_blocks(divHBLKSZ(hhdr -> hb_sz));
       } else {
 	  index = n;
       }
+    }
 #   endif
     if (hhdr -> hb_prev == 0) {
 #	ifdef USE_MUNMAP
+	if (GC_MERCURY_USE_MUNMAP) {
 	  if (FL_UNKNOWN == n) {
             index = GC_hblk_fl_from_blocks(divHBLKSZ(hhdr -> hb_sz));
 	  } else {
 	    index = n;
 	  }
+	}
 #	endif
 	GC_ASSERT(HDR(GC_hblkfreelist[index]) == hhdr);
 	GC_hblkfreelist[index] = hhdr -> hb_next;
@@ -628,8 +640,9 @@
 		&& USED_HEAP_SIZE >= GC_requested_heapsize
 		&& !TRUE_INCREMENTAL && GC_should_collect()) {
 #		ifdef USE_MUNMAP
-		    continue;
-#		else
+		    if (GC_MERCURY_USE_MUNMAP) continue;
+#		endif /* USE_MUNMAP */
+
 		    /* If we have enough large blocks left to cover any	*/
 		    /* previous request for large blocks, we go ahead	*/
 		    /* and split.  Assuming a steady state, that should	*/
@@ -644,7 +657,6 @@
 		    if (GC_finalizer_bytes_freed > (GC_heapsize >> 4))  {
 		      continue;
 		    }
-#		endif /* !USE_MUNMAP */
 	    }
 	    /* If the next heap block is obviously better, go on.	*/
 	    /* This prevents us from disassembling a single large block */
Index: boehm_gc/alloc.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/boehm_gc/alloc.c,v
retrieving revision 1.16
diff -u -r1.16 alloc.c
--- boehm_gc/alloc.c	15 Aug 2006 04:19:23 -0000	1.16
+++ boehm_gc/alloc.c	22 Jan 2008 00:36:52 -0000
@@ -713,7 +713,9 @@
       GC_finalizer_bytes_freed = 0;
       
 #   ifdef USE_MUNMAP
-      GC_unmap_old();
+    if (GC_MERCURY_USE_MUNMAP) {
+	GC_unmap_old();
+    }
 #   endif
     if (GC_print_stats) {
 	GET_TIME(done_time);
Index: boehm_gc/malloc.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/boehm_gc/malloc.c,v
retrieving revision 1.16
diff -u -r1.16 malloc.c
--- boehm_gc/malloc.c	15 Aug 2006 04:19:26 -0000	1.16
+++ boehm_gc/malloc.c	22 Jan 2008 00:36:52 -0000
@@ -53,7 +53,7 @@
 	    GC_collect_a_little_inner((int)n_blocks);
     h = GC_allochblk(lb, k, flags);
 #   ifdef USE_MUNMAP
-	if (0 == h) {
+	if (0 == h && GC_MERCURY_USE_MUNMAP) {
 	    GC_merge_unmapped();
 	    h = GC_allochblk(lb, k, flags);
 	}
Index: boehm_gc/include/gc.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/boehm_gc/include/gc.h,v
retrieving revision 1.17
diff -u -r1.17 gc.h
--- boehm_gc/include/gc.h	15 Aug 2006 04:19:33 -0000	1.17
+++ boehm_gc/include/gc.h	22 Jan 2008 00:36:52 -0000
@@ -230,6 +230,10 @@
 				/* will disable the "pause time exceeded"*/
 				/* tests.				 */
 
+GC_API int GC_mercury_use_munmap;
+				/* Whether to use munmap(). Only	 */
+				/* effective if USE_MUNMAP is defined.   */
+
 /* Public procedures */
 
 /* Initialize the collector.  This is only required when using thread-local
Index: boehm_gc/include/private/gc_priv.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/boehm_gc/include/private/gc_priv.h,v
retrieving revision 1.6
diff -u -r1.6 gc_priv.h
--- boehm_gc/include/private/gc_priv.h	15 Aug 2006 04:19:35 -0000	1.6
+++ boehm_gc/include/private/gc_priv.h	22 Jan 2008 00:36:52 -0000
@@ -1742,6 +1742,10 @@
   void GC_unmap(ptr_t start, size_t bytes);
   void GC_remap(ptr_t start, size_t bytes);
   void GC_unmap_gap(ptr_t start1, size_t bytes1, ptr_t start2, size_t bytes2);
+
+  #define GC_MERCURY_USE_MUNMAP	GC_mercury_use_munmap
+#else
+  #define GC_MERCURY_USE_MUNMAP	0
 #endif
 
 /* Virtual dirty bit implementation:		*/
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.556
diff -u -r1.556 user_guide.texi
--- doc/user_guide.texi	14 Jan 2008 00:08:03 -0000	1.556
+++ doc/user_guide.texi	22 Jan 2008 00:36:52 -0000
@@ -9785,6 +9785,13 @@
 @c bootcheck script (to reduce the time taken for a bootcheck while still
 @c testing the code writing out deep profiling data).
 
+ at sp 1
+ at item --munmap
+ at findex --munmap
+This option enables code in the Boehm garbage collector to return unused memory
+pages back to the operating system. It is meaningful only when using the Boehm
+garbage collector, and requires @samp{--enable-gc-munmap} to be passed to
+ at samp{configure} (which may not work with all platforms).
 @end table
 
 @sp 1
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.186
diff -u -r1.186 mercury_wrapper.c
--- runtime/mercury_wrapper.c	7 Dec 2007 02:06:26 -0000	1.186
+++ runtime/mercury_wrapper.c	22 Jan 2008 00:36:53 -0000
@@ -1108,7 +1108,8 @@
     MR_COVERAGE_TEST_OPT,
     MR_COVERAGE_TEST_IF_EXEC_OPT,
     MR_TRACE_COUNT_FILE,
-    MR_MEM_USAGE_REPORT
+    MR_MEM_USAGE_REPORT,
+    MR_MUNMAP
 };
 
 struct MR_option MR_long_opts[] = {
@@ -1207,6 +1208,7 @@
     { "tc-summary-max",                 1, 0, MR_TRACE_COUNT_SUMMARY_MAX_OPT },
     { "trace-count-summary-max",        1, 0, MR_TRACE_COUNT_SUMMARY_MAX_OPT },
     { "mem-usage-report",               1, 0, MR_MEM_USAGE_REPORT },
+    { "munmap",                         0, 0, MR_MUNMAP },
 
     /* This needs to be kept at the end. */
     { NULL,                             0, 0, 0 }
@@ -1731,6 +1733,12 @@
                 MR_mem_usage_report_prefix = MR_copy_string(MR_optarg);
                 break;
 
+            case MR_MUNMAP:
+#ifdef MR_BOEHM_GC
+                GC_mercury_use_munmap = MR_TRUE;
+#endif
+                break;
+
             case 'a':
                 benchmark_all_solns = MR_TRUE;
                 break;

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list