aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpennae <github@quasiparticle.net>2021-12-26 19:32:08 +0100
committerpennae <github@quasiparticle.net>2022-03-08 23:30:18 +0100
commit60ed4e908a59f258f82356a9dd47e43361d39f2f (patch)
tree0c94dac64ef4e103495da255d46253212a993837 /src
parent4b2b0d3a5528133898a15f3210c79162ec993823 (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.cc21
-rw-r--r--src/libexpr/eval.hh3
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(