Skip to content

Comments

Lazy trees v2#27

Merged
edolstra merged 34 commits intodetsys-mainfrom
lazy-trees-v2
May 7, 2025
Merged

Lazy trees v2#27
edolstra merged 34 commits intodetsys-mainfrom
lazy-trees-v2

Conversation

@edolstra
Copy link
Collaborator

@edolstra edolstra commented Apr 8, 2025

Motivation

Less invasive variant of NixOS#6530. 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).

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.

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).
@github-actions
Copy link

github-actions bot commented Apr 8, 2025

@github-actions github-actions bot temporarily deployed to pull request April 8, 2025 22:24 Inactive
@github-actions github-actions bot temporarily deployed to pull request April 9, 2025 21:36 Inactive
@github-actions github-actions bot temporarily deployed to pull request April 10, 2025 11:17 Inactive
@github-actions github-actions bot temporarily deployed to pull request April 14, 2025 13:11 Inactive
Borrowed from the original lazy-trees branch.
@github-actions github-actions bot temporarily deployed to pull request April 15, 2025 17:08 Inactive
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.
@github-actions github-actions bot temporarily deployed to pull request April 18, 2025 15:11 Inactive
@github-actions github-actions bot temporarily deployed to pull request May 6, 2025 17:22 Inactive
@grahamc grahamc marked this pull request as ready for review May 6, 2025 19:00
@grahamc grahamc enabled auto-merge May 6, 2025 19:02
@grahamc grahamc disabled auto-merge May 6, 2025 19:05
@gustavderdrache
Copy link

The diff looks about right, and some testing locally shows some decent eval speedups.

@github-actions github-actions bot temporarily deployed to pull request May 7, 2025 11:00 Inactive
@github-actions github-actions bot temporarily deployed to pull request May 7, 2025 12:19 Inactive
@@ -83,8 +83,16 @@ StorePath EvalState::mountInput(
}

// FIXME: what to do with the NAR hash in lazy mode?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this fixme'd?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but we can postpone this for now.

@github-actions github-actions bot temporarily deployed to pull request May 7, 2025 13:36 Inactive
@github-actions github-actions bot temporarily deployed to pull request May 7, 2025 14:05 Inactive
@edolstra edolstra enabled auto-merge May 7, 2025 14:18
Copy link
Member

@grahamc grahamc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 total

But 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 total

And 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:

curl -fsSL https://install.determinate.systems/nix | sh -s -- install --determinate

Important

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:

  1. opening an issue here
  2. joining our Discord
  3. 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.

@edolstra edolstra added this pull request to the merge queue May 7, 2025
Merged via the queue into detsys-main with commit df93fa8 May 7, 2025
26 checks passed
@edolstra edolstra deleted the lazy-trees-v2 branch May 7, 2025 15:33
@yacinehmito yacinehmito mentioned this pull request May 11, 2025
9 tasks
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

Successfully merging this pull request may close these issues.

4 participants