Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache evaluation for eval and flake check #4279

Open
balsoft opened this issue Nov 24, 2020 · 9 comments
Open

Cache evaluation for eval and flake check #4279

balsoft opened this issue Nov 24, 2020 · 9 comments

Comments

@balsoft
Copy link
Member

balsoft commented Nov 24, 2020

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.

@stale
Copy link

stale bot commented Jun 2, 2021

I marked this as stale due to inactivity. → More info

@stale stale bot added the stale label Jun 2, 2021
@ncfavier
Copy link
Member

Still an issue

@stale stale bot removed the stale label Jun 20, 2021
@thufschmitt
Copy link
Member

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

@stale
Copy link

stale bot commented Jan 3, 2022

I marked this as stale due to inactivity. → More info

@stale stale bot added the stale label Jan 3, 2022
@tomberek
Copy link
Contributor

still an issue

@stale stale bot removed the stale label Jan 23, 2022
@stale stale bot added the stale label Aug 1, 2022
@stale stale bot removed the stale label Dec 5, 2022
@nrdxp
Copy link

nrdxp commented Dec 9, 2022

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.

@tomberek
Copy link
Contributor

tomberek commented Jan 8, 2023

@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: 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?

@edolstra edolstra self-assigned this Aug 18, 2023
@edolstra edolstra removed this from Nix team Aug 18, 2023
@Ericson2314
Copy link
Member

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

@nixos-discourse
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants