Conversation
These don't need to evaluate anything (except for the flake metadata in flake.nix) so we can make these commands operate on lazy trees without risk of any semantic change in the evaluator. However, `nix flake metadata` now no longer prints the store path, which is a breaking change (but unavoidable if we want lazy trees).
For the top-level flake, we don't need a NAR hash. But for inputs, we do. Also, add a test for the lazy behaviour of `nix flake metadata|lock`.
We now mount lazy accessors on top of /nix/store without materializing them, and only materialize them to the real store if needed (e.g. in the `derivation` primop).
Something went wrong in NixOS#12068 so this didn't work. Also added a test.
Also, make fetchTree use InputCache.
Borrowed from the original lazy-trees branch.
This is needed to devirtualize them when they get passed to a derivation or builtins.toFile. Arguably, since this builtin is unsafe, we could just ignore this, but we may as well do the correct thing.
|
The diff looks about right, and some testing locally shows some decent eval speedups. |
Co-authored-by: Cole Helbling <[email protected]>
| @@ -83,8 +83,16 @@ StorePath EvalState::mountInput( | |||
| } | |||
|
|
|||
| // FIXME: what to do with the NAR hash in lazy mode? | |||
There was a problem hiding this comment.
No, but we can postpone this for now.
There was a problem hiding this comment.
I'm glad to merge this.
Why we built this
Using Nix and flakes in large-scale situations, like monorepos, is currently very painful and slow.
That's because Nix copies the entire repository to the Nix store on every nix command.
This is a minor annoyance on small projects but on some larger projects it essentially makes Nix a non-starter.
Adding lazy trees massively improves performance in virtually all scenarios because it enables Nix to avoid making unnecessary copies of files into the Nix store.
For comparison, working on Nixpkgs takes over 12 seconds on my M3 MacBook Pro:
$ echo "" >> flake.nix
$ time NIX_CONFIG="lazy-trees = false" nix build --no-eval-cache .#hello
2.04s user 3.95s system 46% cpu 12.902 totalBut with lazy trees enabled, that time is cut down to a much more manageable 3.6 seconds:
$ echo "" >> flake.nix
$ time NIX_CONFIG="lazy-trees = true" nix build --no-eval-cache .#hello
1.38s user 2.12s system 94% cpu 3.683 totalAnd with evaluation caching (which we aim to also improve soon) the performance is enhanced even further.
Why we're shipping this now
Our upstream pull request has been open for three years (since May 12, 2022) and has been fairly continuously kept up to date.
We've set out to build Determinate Nix because we want to be able to build, merge, and deliver improvements to our users faster.
That includes features like lazy trees, which may need time to "bake" in users' hands.
Our hope is that by shipping Nix with lazy trees to users, initially on an opt-in basis, we'll be able to validate its stability and robustness and to enable the upstream project to ultimately merge it themselves when they're ready.
Next steps
Before we make a tagged Determinate Nix release with this merge, we will have opened up PRs for any remaining implementation details that are not yet in upstream PRs already.
Status
For clarity, the status of lazy trees is currently experimental and it may be broken or removed at any moment.
Even when this PR merges, it is not yet shipped but it will ship soon.
When it is in a release, it will default to off (lazy-trees = false) and users will need to specifically turn it on by updating /etc/nix/nix.custom.conf with this line...
lazy-trees = true
...and restarting the Determinate Nix daemon.
Changes in behavior
There are a few subtle changes in user-observable behavior with lazy trees, specifically around unsafe Nix functions.
We'll be updating this comment and docs with details soon.
What if I don't want it yet?
Users who do not explicitly turn it on shouldn't see any change in Nix's behavior.
How can I try it now?
We'll be shipping Determinate Nix 3.5 in the next ~7 days, perhaps by the end of this week.
When it ships, run sudo determinate-nixd upgrade to upgrade Determinate Nix, make a configuration change, and you'll be squared away.
If you don't have Determinate Nix yet:
- macOS users: download and run the macOS package from https://docs.determinate.systems to switch.
- NixOS users: add our NixOS module: https://docs.determinate.systems/guides/advanced-installation/#nixos
- Other Linux and WSL users: the easiest way is to uninstall Nix and reinstall with Determinate:
curl -fsSL https://install.determinate.systems/nix | sh -s -- install --determinateImportant
What if I want it RIGHT NOW right now? Join us on Discord and we can get you hooked up with upgrade instructions!
How can I help?
Whether you use lazy trees or not, please report bugs about this change.
If you see a change without turning on lazy trees, that is a major problem.
If you turn on lazy trees and it did something unexpected, we'd like to know that too.
Please report a bug by:
- opening an issue here
- joining our Discord
- emailing
[email protected]
And in any case, please run determinate-nixd bug and include the ID that the tool prints so that we can understand the issue better.
Motivation
Less invasive variant of NixOS#6530. We now mount lazy accessors on top of
/nix/storewithout materializing them, and only materialize them to the real store if needed (e.g. in thederivationprimop).The virtual store paths for the lazy accessors are currently random. This could be replaced by something more deterministic if desired.
Incorporates NixOS#12432.
Context
Add 👍 to pull requests you find important.
The Nix maintainer team uses a GitHub project board to schedule and track reviews.