nix
nix copied to clipboard
Cache evaluation for eval and flake check
Is your feature request related to a problem? Please describe.
Running nix flake check
multiple times without changing the repository can take way too long. For flakes describing multiple NixOS systems all of which depend on programs built with IFD-heavy haskell.nix
, nix flake check
can take 10s of seconds.
Describe the solution you'd like
It would be very useful if nix eval
and nix flake check
used evaluation caching.
I marked this as stale due to inactivity. → More info
Still an issue
I have some WIP to fix this on https://github.com/NixOS/nix/tree/eval-cache . It’s still a WIP because the performance isn’t on par with the current cache. But if someone wants to have a second look at it to see what could be made faster, that could help a lot
I marked this as stale due to inactivity. → More info
still an issue
In divnix/std-action we run one mass evaluation up front and then share those results using the github action cache to a myriad of task runners built from a specialized json. Since the process of calling this evauation also reifies any referenced derivations to disk, we can then call any task runners or builder jobs directly on the drv files themselves.
The idea is to allow the runners to avoid the cost of running Nix evaluations at all and instead allow them to get to work immediately. If the eval cache was popullated from nix eval
it would only make our process that much more efficient; saving time right where it counts as the discovery evaluation is the bottleneck for all the rest of the work.
@thufschmitt is there something wrong with something along these lines? It seems that eval does populate the cache, but does not use it. Other code paths like nix build
know the type of what is requested, thus use the appropriate getter, but eval
does not.
link: https://github.com/NixOS/nix/compare/master...flox:nix:eval_eval_cache
diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc
index afe575fee..fe0ba3211 100644
--- a/src/libexpr/eval-cache.cc
+++ b/src/libexpr/eval-cache.cc
@@ -382,6 +382,30 @@ AttrKey AttrCursor::getKey()
Value & AttrCursor::getValue()
{
+ if (root->db) {
+ if (!cachedValue)
+ cachedValue = root->db->getAttr(getKey());
+ if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
+ if (auto s = std::get_if<string_t>(&cachedValue->second)) {
+ debug("using cached string attribute '%s'", getAttrPathStr());
+ auto v = root->state.allocValue();
+ v->mkString(s->first);
+ return *v;
+ }
+ else if (auto s = std::get_if<bool>(&cachedValue->second)) {
+ debug("using cached bool attribute '%s'", getAttrPathStr());
+ auto v = root->state.allocValue();
+ v->mkBool(*s);
+ return *v;
+ }
+ else if (auto s = std::get_if<int_t>(&cachedValue->second)) {
+ debug("using cached int attribute '%s'", getAttrPathStr());
+ auto v = root->state.allocValue();
+ v->mkInt(s->x);
+ return *v;
+ }
+ }
+ }
if (!_value) {
if (parent) {
auto & vParent = parent->first->getValue();
Perhaps the performance cost on many misses?
Briefly discussed in the Nix team meeting
-
@roberth: Remember we don't yet store evaluation errors in the eval cache. For these commands where showing errors / not excluding failures is the point, we should be wary of using the Eval cache until it is improved.
-
@edolstra: Yeah will look into that too.
Assigned to @edolstra
This issue has been mentioned on NixOS Discourse. There might be relevant details there:
https://discourse.nixos.org/t/2023-08-18-nix-team-meeting-minutes-80/32081/1