Skip to content

Stack sampling flamegraph profiler#13220

Merged
Mic92 merged 3 commits intoNixOS:masterfrom
xokdvium:flamegraph
May 23, 2025
Merged

Stack sampling flamegraph profiler#13220
Mic92 merged 3 commits intoNixOS:masterfrom
xokdvium:flamegraph

Conversation

@xokdvium
Copy link
Contributor

@xokdvium xokdvium commented May 17, 2025

Motivation

This patch adds support for a native stack sampling
profiler to the evaluator, which saves a collapsed stack
profile information to a configurable location.

Introduced options (in EvalSettings):

  • eval-profile-file - path to the collected profile file.

  • eval-profiler-sample-period eval-profiler-frequency - sampling frequency.

  • eval-profiler - enumeration option for enabling the profiler.

    Currently only flamegraph is supported, but having this an
    enumeration rather than a boolean switch leaves the door open
    for other profiler variants (e.g. tracy).

Profile includes the following information on best-effort basis (e.g. some lambdas might
have an undefined name). Callstack information contains:

  • Call site location (where the function gets called).
  • Primop/lambda name of the function being called.
  • Functors/partial applications don't have a name attached to them unlike special-cased primops and lambdas.

For cases where callsite location isn't available we have to resort to providing
the location where the lambda itself is defined. This removes some of the confusing
«none»:0 locations in the profile from #11373.

Example usage with piping directly into zstd for compression:

nix eval --no-eval-cache nixpkgs#nixosTests.gnome \
  --option eval-profiler flamegraph \
  --option eval-profile-file >(zstd -of nix.profile.zstd)
Sample profile for `nixosTests.gnome` with 99Hz sampling frequency

(Updated to 99Hz default)

nix eval --no-eval-cache nixpkgs#nixosTests.gnome \
  --eval-profiler flamegraph \
  --eval-profile-file >(zstd -of nix.profile.zstd)
zstd -d nix.profile.zstd

image
nix.profile.gz

Context

This builds upon #11373 and hopefully leaves room for other profiler implementations like #9967.


Add 👍 to pull requests you find important.

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

@xokdvium xokdvium requested a review from edolstra as a code owner May 17, 2025 11:11
@xokdvium xokdvium marked this pull request as draft May 17, 2025 11:13
@Mic92
Copy link
Member

Mic92 commented May 18, 2025

Needs a rebase.

@xokdvium xokdvium force-pushed the flamegraph branch 3 times, most recently from 113be6c to 7c25744 Compare May 18, 2025 22:55
@github-actions github-actions bot added the with-tests Issues related to testing. PRs with tests have some priority label May 18, 2025
@xokdvium xokdvium changed the title WIP: Stack sampling profiler Stack sampling flamegraph profiler May 18, 2025
@xokdvium xokdvium force-pushed the flamegraph branch 3 times, most recently from 5ef4e67 to a80e026 Compare May 18, 2025 23:12
@xokdvium
Copy link
Contributor Author

Rebased, pushed a more polished version with tests and added an example profile for nixosTests.gnome. Hopefully this passes all CI checks.

@xokdvium xokdvium marked this pull request as ready for review May 18, 2025 23:17
@xokdvium xokdvium force-pushed the flamegraph branch 2 times, most recently from 7acd364 to 0275cb3 Compare May 19, 2025 09:02
xokdvium and others added 3 commits May 21, 2025 20:15
This patch adds support for a native stack sampling
profiler to the evaluator, which saves a collapsed stack
profile information to a configurable location.

Introduced options (in `EvalSettings`):

- `eval-profile-file` - path to the collected profile file.
- `eval-profiler-frequency` - sampling frequency.
- `eval-profiler` - enumeration option for enabling the profiler.

  Currently only `flamegraph` is supported, but having this an
  enumeration rather than a boolean switch leaves the door open
  for other profiler variants (e.g. tracy).

Profile includes the following information on best-effort basis (e.g. some lambdas might
have an undefined name). Callstack information contains:

- Call site location (where the function gets called).
- Primop/lambda name of the function being called.
- Functors/partial applications don't have a name attached to them unlike special-cased primops and lambads.

For cases where callsite location isn't available we have to resort to providing
the location where the lambda itself is defined. This removes some of the confusing
`«none»:0` locations in the profile from previous attempts.

Example usage with piping directly into zstd for compression:

```
nix eval --no-eval-cache nixpkgs#nixosTests.gnome \
  --eval-profiler flamegraph \
  --eval-profile-file >(zstd -of nix.profile.zstd)
```

Co-authored-by: Jörg Thalheim <joerg@thalheim.io>
The tests are mostly based on existing `function-trace.sh`
with some tests for corner cases.
@xokdvium
Copy link
Contributor Author

@Mic92, @roberth added a bit of docs and a release note. For now I've put the docs under advanced topics in the manual. Not sure if there's a more fitting place for that.

@Mic92 Mic92 merged commit 906cc88 into NixOS:master May 23, 2025
12 checks passed
@Mic92
Copy link
Member

Mic92 commented May 23, 2025

Nice looks good to me!

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/a-look-at-nixos-nixpkgs-evaluation-times-over-the-years/65114/3

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2025-05-21-nix-team-meeting-minutes-228/65204/1

eljamm added a commit to eljamm/perfanno.nvim that referenced this pull request Jun 15, 2025
This is useful for stack traces that have more information than the
`file:line count` format.

For example, the [Nix language's evaluator
profiler](NixOS/nix#13220) also includes
information about the function being called, which sometimes has a
non-canonical call site location and therefore cannot be annotated.

Here is what this might look like:

```log
<nix/derivation-internal.nix>:37:12:primop derivationStrict
```

As such, with this change, we effectively skip annotating frames that
don't conform to the `file:line count` format.
eljamm added a commit to eljamm/perfanno.nvim that referenced this pull request Jun 15, 2025
This is useful for stack traces that have more information than the
`file:line count` format.

For example, the [Nix language's evaluator
profiler](NixOS/nix#13220) also includes
information about the function being called, which sometimes has a
non-canonical call site location and therefore cannot be annotated.

Here is how this might look like:

```log
<nix/derivation-internal.nix>:37:12:primop derivationStrict
```

As such, with this change, we effectively skip annotating frames that
don't conform to the `file:line count` format.
eljamm added a commit to eljamm/perfanno.nvim that referenced this pull request Jun 15, 2025
This is useful for stack traces that have more information than the
`file:line count` format.

For example, the [Nix language's evaluator
profiler](NixOS/nix#13220) also includes
information about the function being called, which sometimes has a
non-canonical call site location and therefore cannot be annotated.

Here is how this might look like:

```log
<nix/derivation-internal.nix>:37:12:primop derivationStrict
```

As such, with this change, we effectively skip annotating frames that
don't conform to the `file:line count` format.
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/nix-2-30-0-released/66449/1

@roberth roberth added the backports ignored Seen but not applied label Jul 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backports ignored Seen but not applied documentation with-tests Issues related to testing. PRs with tests have some priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants