about summary refs log tree commit diff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2011-02-10T14·31+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2011-02-10T14·31+0000
commit538b7caab013e6ec78bed2b65a7c5d345f1c737e (patch)
tree8eeabda8f593d6adcfe815c807ab2a07cf4ba3a1 /src/libexpr/eval.cc
parent5a6b0398026a8a24b206a4b4d43894f9c683792c (diff)
* Don't allocate a big initial GC address space on machines with
  little RAM.  Even if the memory isn't actually used, it can cause
  problems with the overcommit heuristics in the kernel.  So use a VM
  space of 25% of RAM, up to 384 MB.

Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc35
1 files changed, 24 insertions, 11 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index b95c9a6d17..949f45e787 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -7,6 +7,7 @@
 #include "globals.hh"
 
 #include <cstring>
+#include <unistd.h>
 
 #if HAVE_BOEHMGC
 
@@ -155,17 +156,29 @@ EvalState::EvalState()
 #if HAVE_BOEHMGC
     static bool gcInitialised = true;
     if (gcInitialised) {
-        /* Set the initial heap size to something fairly big (384 MiB)
-           so that in most cases we don't need to garbage collect at
-           all.  (Collection has a fairly significant overhead.)  The
-           heap size can be overriden through libgc's
-           GC_INITIAL_HEAP_SIZE environment variable.  We should
-           probably also provide a nix.conf setting for this.  Note
-           that GC_expand_hp() causes a lot of virtual, but not
-           physical (resident) memory to be allocated.  This might be
-           a problem on systems that don't overcommit. */
-        if (!getenv("GC_INITIAL_HEAP_SIZE"))
-            GC_expand_hp(384 * 1024 * 1024);
+        /* Set the initial heap size to something fairly big (25% of
+           physical RAM, up to a maximum of 384 MiB) so that in most
+           cases we don't need to garbage collect at all.  (Collection
+           has a fairly significant overhead.)  The heap size can be
+           overriden through libgc's GC_INITIAL_HEAP_SIZE environment
+           variable.  We should probably also provide a nix.conf
+           setting for this.  Note that GC_expand_hp() causes a lot of
+           virtual, but not physical (resident) memory to be
+           allocated.  This might be a problem on systems that don't
+           overcommit. */
+        if (!getenv("GC_INITIAL_HEAP_SIZE")) {
+            size_t maxSize = 384 * 1024 * 1024;
+            size_t size = 32 * 1024 * 1024;
+#if HAVE_SYSCONF && defined(_SC_PAGESIZE) && defined(_SC_PHYS_PAGES)
+            long pageSize = sysconf(_SC_PAGESIZE);
+            long pages = sysconf (_SC_PHYS_PAGES);
+            if (pageSize != -1 && size != -1)
+                size = (pageSize * pages) / 4; // 25% of RAM
+            if (size > maxSize) size = maxSize;
+#endif
+            debug(format("setting initial heap size to %1% bytes") % size);
+            GC_expand_hp(size);
+        }
         gcInitialised = true;
     }
 #endif