diff options
author | pennae <github@quasiparticle.net> | 2021-12-26 19:32:08 +0100 |
---|---|---|
committer | pennae <github@quasiparticle.net> | 2022-03-08 23:30:18 +0100 |
commit | 60ed4e908a59f258f82356a9dd47e43361d39f2f (patch) | |
tree | 0c94dac64ef4e103495da255d46253212a993837 /src | |
parent | 4b2b0d3a5528133898a15f3210c79162ec993823 (diff) |
cache singleton Envs just like Values
vast majority of envs is this size.
before:
Benchmark 1: nix flakes search --no-eval-cache --offline ../nixpkgs hello
Time (mean ± σ): 6.946 s ± 0.041 s [User: 5.875 s, System: 0.835 s]
Range (min … max): 6.834 s … 7.005 s 20 runs
Benchmark 2: nix flakes eval -f ../nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix
Time (mean ± σ): 330.3 ms ± 2.5 ms [User: 299.2 ms, System: 30.9 ms]
Range (min … max): 327.5 ms … 337.7 ms 20 runs
Benchmark 3: nix eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system'
Time (mean ± σ): 2.671 s ± 0.035 s [User: 2.370 s, System: 0.232 s]
Range (min … max): 2.597 s … 2.749 s 20 runs
after:
Benchmark 1: nix flakes search --no-eval-cache --offline ../nixpkgs hello
Time (mean ± σ): 6.935 s ± 0.052 s [User: 5.852 s, System: 0.853 s]
Range (min … max): 6.808 s … 7.026 s 20 runs
Benchmark 2: nix flakes eval -f ../nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix
Time (mean ± σ): 329.8 ms ± 2.7 ms [User: 299.0 ms, System: 30.8 ms]
Range (min … max): 326.6 ms … 336.5 ms 20 runs
Benchmark 3: nix flakes eval --raw --impure --file expr.nix
Time (mean ± σ): 2.655 s ± 0.038 s [User: 2.364 s, System: 0.220 s]
Range (min … max): 2.574 s … 2.737 s 20 runs
Diffstat (limited to 'src')
-rw-r--r-- | src/libexpr/eval.cc | 21 | ||||
-rw-r--r-- | src/libexpr/eval.hh | 3 |
2 files changed, 23 insertions, 1 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 777f6a4ec..ddbbdeaa6 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -438,8 +438,10 @@ EvalState::EvalState( , regexCache(makeRegexCache()) #if HAVE_BOEHMGC , valueAllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr)) + , env1AllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr)) #else , valueAllocCache(std::make_shared<void *>(nullptr)) + , env1AllocCache(std::make_shared<void *>(nullptr)) #endif , baseEnv(allocEnv(128)) , staticBaseEnv(false, 0) @@ -892,7 +894,24 @@ Env & EvalState::allocEnv(size_t size) { nrEnvs++; nrValuesInEnvs += size; - Env * env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *)); + + Env * env; + + if (size != 1) + env = (Env *) allocBytes(sizeof(Env) + size * sizeof(Value *)); + else { + /* see allocValue for explanations. */ + if (!*env1AllocCache) { + *env1AllocCache = GC_malloc_many(sizeof(Env) + sizeof(Value *)); + if (!*env1AllocCache) throw std::bad_alloc(); + } + + void * p = *env1AllocCache; + *env1AllocCache = GC_NEXT(p); + GC_NEXT(p) = nullptr; + env = (Env *) p; + } + env->type = Env::Plain; /* We assume that env->values has been cleared by the allocator; maybeThunk() and lookupVar fromWith expect this. */ diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 800b00eef..41384f044 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -136,6 +136,9 @@ private: /* Allocation cache for GC'd Value objects. */ std::shared_ptr<void *> valueAllocCache; + /* Allocation cache for size-1 Env objects. */ + std::shared_ptr<void *> env1AllocCache; + public: EvalState( |