diff options
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/attr-set.cc | 16 | ||||
-rw-r--r-- | src/libexpr/eval-inline.hh | 14 | ||||
-rw-r--r-- | src/libexpr/eval.cc | 72 | ||||
-rw-r--r-- | src/libexpr/eval.hh | 9 |
4 files changed, 71 insertions, 40 deletions
diff --git a/src/libexpr/attr-set.cc b/src/libexpr/attr-set.cc index 0474865c6d7d..0785897d2513 100644 --- a/src/libexpr/attr-set.cc +++ b/src/libexpr/attr-set.cc @@ -1,5 +1,5 @@ #include "attr-set.hh" -#include "eval.hh" +#include "eval-inline.hh" #include <algorithm> @@ -7,20 +7,6 @@ namespace nix { -/* Note: Various places expect the allocated memory to be zeroed. */ -static void * allocBytes(size_t n) -{ - void * p; -#if HAVE_BOEHMGC - p = GC_malloc(n); -#else - p = calloc(n, 1); -#endif - if (!p) throw std::bad_alloc(); - return p; -} - - /* Allocate a new array of attributes for an attribute set with a specific capacity. The space is implicitly reserved after the Bindings structure. */ diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh index 8cc50e561354..c27116e3b448 100644 --- a/src/libexpr/eval-inline.hh +++ b/src/libexpr/eval-inline.hh @@ -78,4 +78,18 @@ inline void EvalState::forceList(Value & v, const Pos & pos) throwTypeError("value is %1% while a list was expected, at %2%", v, pos); } +/* Note: Various places expect the allocated memory to be zeroed. */ +inline void * allocBytes(size_t n) +{ + void * p; +#if HAVE_BOEHMGC + p = GC_MALLOC(n); +#else + p = calloc(n, 1); +#endif + if (!p) throw std::bad_alloc(); + return p; +} + + } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 517952164a97..e09297546c95 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -13,17 +13,14 @@ #include <sys/time.h> #include <sys/resource.h> +#include <sys/time.h> +#include <sys/resource.h> + #if HAVE_BOEHMGC #include <gc/gc.h> #include <gc/gc_cpp.h> -#define NEW new (UseGC) - -#else - -#define NEW new - #endif @@ -34,7 +31,7 @@ static char * dupString(const char * s) { char * t; #if HAVE_BOEHMGC - t = GC_strdup(s); + t = GC_STRDUP(s); #else t = strdup(s); #endif @@ -43,20 +40,6 @@ static char * dupString(const char * s) } -/* Note: Various places expect the allocated memory to be zeroed. */ -static void * allocBytes(size_t n) -{ - void * p; -#if HAVE_BOEHMGC - p = GC_malloc(n); -#else - p = calloc(n, 1); -#endif - if (!p) throw std::bad_alloc(); - return p; -} - - static void printValue(std::ostream & str, std::set<const Value *> & active, const Value & v) { checkInterrupt(); @@ -199,8 +182,15 @@ void initGC() #if HAVE_BOEHMGC /* Initialise the Boehm garbage collector. */ + + /* Don't look for interior pointers. This reduces the odds of + misdetection a bit. */ GC_set_all_interior_pointers(0); + /* We don't have any roots in data segments, so don't scan from + there. */ + GC_set_no_dls(1); + GC_INIT(); GC_set_oom_fn(oomHandler); @@ -346,7 +336,6 @@ EvalState::EvalState(const Strings & _searchPath, ref<Store> store) EvalState::~EvalState() { - fileEvalCache.clear(); } @@ -451,7 +440,7 @@ Value * EvalState::addPrimOp(const string & name, string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; Symbol sym = symbols.create(name2); v->type = tPrimOp; - v->primOp = NEW PrimOp(primOp, arity, sym); + v->primOp = new PrimOp(primOp, arity, sym); staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; baseEnv.values[baseEnvDispl++] = v; baseEnv.values[0]->attrs->push_back(Attr(sym, v)); @@ -589,10 +578,19 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval) } +std::atomic<uint64_t> nrValuesFreed{0}; + +void finalizeValue(void * obj, void * data) +{ + nrValuesFreed++; +} + Value * EvalState::allocValue() { nrValues++; - return (Value *) allocBytes(sizeof(Value)); + auto v = (Value *) allocBytes(sizeof(Value)); + //GC_register_finalizer_no_order(v, finalizeValue, nullptr, nullptr, nullptr); + return v; } @@ -725,7 +723,17 @@ void EvalState::evalFile(const Path & path_, Value & v) } printTalkative("evaluating file '%1%'", path2); - Expr * e = parseExprFromFile(checkSourcePath(path2)); + Expr * e = nullptr; + + auto j = fileParseCache.find(path2); + if (j != fileParseCache.end()) + e = j->second; + + if (!e) + e = parseExprFromFile(checkSourcePath(path2)); + + fileParseCache[path2] = e; + try { eval(e, v); } catch (Error & e) { @@ -1712,6 +1720,20 @@ bool EvalState::eqValues(Value & v1, Value & v2) } +void EvalState::printStats2() +{ + struct rusage ru; + getrusage(RUSAGE_SELF, &ru); + + GC_prof_stats_s gc; + GC_get_prof_stats(&gc, sizeof(gc)); + + printError("STATS %d %d %d %d %d %d", + nrValues, nrValuesFreed.load(), nrValues - nrValuesFreed, + ru.ru_maxrss, + gc.heapsize_full, gc.free_bytes_full); +} + void EvalState::printStats() { bool showStats = getEnv("NIX_SHOW_STATS", "0") != "0"; diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 146f21255034..46bda86d084e 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -90,6 +90,14 @@ public: private: SrcToStore srcToStore; + /* A cache from path names to parse trees. */ +#if HAVE_BOEHMGC + typedef std::map<Path, Expr *, std::less<Path>, traceable_allocator<std::pair<const Path, Expr *> > > FileParseCache; +#else + typedef std::map<Path, Expr *> FileParseCache; +#endif + FileParseCache fileParseCache; + /* A cache from path names to values. */ #if HAVE_BOEHMGC typedef std::map<Path, Value, std::less<Path>, traceable_allocator<std::pair<const Path, Value> > > FileEvalCache; @@ -268,6 +276,7 @@ public: /* Print statistics. */ void printStats(); + void printStats2(); void realiseContext(const PathSet & context); |