Skip to content

libexpr: Actually cache line information in PosTable#13211

Merged
Ericson2314 merged 2 commits intoNixOS:masterfrom
xokdvium:pos-table
May 16, 2025
Merged

libexpr: Actually cache line information in PosTable#13211
Ericson2314 merged 2 commits intoNixOS:masterfrom
xokdvium:pos-table

Conversation

@xokdvium
Copy link
Contributor

@xokdvium xokdvium commented May 15, 2025

Motivation

Previous code had a sneaky bug due to which no caching
actually happened:

auto linesForInput = (*lines)[origin->offset];

That should have been:

auto & linesForInput = (*lines)[origin->offset];

See 1.

Now that it also makes sense to make the cache bound in size
in order not to memoize all the sources without freeing any memory.
The default cache size has been chosen somewhat arbitrarily to be ~64k
origins. For reference, 25.05 nixpkgs has ~50k .nix files.

Simple benchmark:

let
  pkgs = import <nixpkgs> { };
in
builtins.foldl' (acc: el: acc + el.line) 0 (
  builtins.genList (x: builtins.unsafeGetAttrPos "gcc" pkgs) 10000
)

(After)

$ hyperfine "result/bin/nix eval -f ./test.nix"
Benchmark 1: result/bin/nix eval -f ./test.nix
  Time (mean ± σ):     292.7 ms ±   3.9 ms    [User: 131.0 ms, System: 120.5 ms]
  Range (min … max):   288.1 ms … 300.5 ms    10 runs

(Before)

hyperfine "nix eval -f ./test.nix"
Benchmark 1: nix eval -f ./test.nix
  Time (mean ± σ):     666.7 ms ±   6.4 ms    [User: 428.3 ms, System: 191.2 ms]
  Range (min … max):   659.7 ms … 681.3 ms    10 runs

If the origin happens to be a all-packages.nix or similar in size then the
difference is much more dramatic.

Context

#12645 (comment)

@roberth As it turns out the PosTable was indeed supposed to do the caching, but didn't due to the bug I described above.


Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

xokdvium added 2 commits May 15, 2025 22:28
For heavier objects it doesn't make sense to return
a std::optional with the copy of the data, when it
can be used by const reference.
Previous code had a sneaky bug due to which no caching
actually happened:

```cpp
auto linesForInput = (*lines)[origin->offset];
```

That should have been:
```cpp
auto & linesForInput = (*lines)[origin->offset];
```

See [1].

Now that it also makes sense to make the cache bound in side
in order not to memoize all the sources without freeing any memory.
The default cache size has been chosen somewhat arbitrarily to be ~64k
origins. For reference, 25.05 nixpkgs has ~50k .nix files.

Simple benchmark:

```nix
let
  pkgs = import <nixpkgs> { };
in
builtins.foldl' (acc: el: acc + el.line) 0 (
  builtins.genList (x: builtins.unsafeGetAttrPos "gcc" pkgs) 10000
)
```

(After)

```
$ hyperfine "result/bin/nix eval -f ./test.nix"
Benchmark 1: result/bin/nix eval -f ./test.nix
  Time (mean ± σ):     292.7 ms ±   3.9 ms    [User: 131.0 ms, System: 120.5 ms]
  Range (min … max):   288.1 ms … 300.5 ms    10 runs
```

(Before)

```
hyperfine "nix eval -f ./test.nix"
Benchmark 1: nix eval -f ./test.nix
  Time (mean ± σ):     666.7 ms ±   6.4 ms    [User: 428.3 ms, System: 191.2 ms]
  Range (min … max):   659.7 ms … 681.3 ms    10 runs
```

If the origin happens to be a `all-packages.nix` or similar in size then the
difference is much more dramatic.

[1]: https://www.github.com/lix-project/lix/commit/22e3f0e9875082be7f4eec8e3caeb134a7f1c05f
@xokdvium xokdvium requested a review from edolstra as a code owner May 15, 2025 23:08
@Ericson2314 Ericson2314 merged commit b21fc05 into NixOS:master May 16, 2025
13 checks passed
@xokdvium xokdvium deleted the pos-table branch May 16, 2025 07:49
@roberth roberth added backports created Does not require attention and can be filtered away backport 2.28-maintenance Automatically creates a PR against the branch backport 2.29-maintenance Automatically creates a PR against the branch labels Jul 30, 2025
mergify bot added a commit that referenced this pull request Jul 30, 2025
…3211

libexpr: Actually cache line information in PosTable (backport #13211)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport 2.28-maintenance Automatically creates a PR against the branch backport 2.29-maintenance Automatically creates a PR against the branch backports created Does not require attention and can be filtered away

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants