Skip to content

Stack sampling flamegraph profiler #13220

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

Merged
merged 3 commits into from
May 23, 2025
Merged

Stack sampling flamegraph profiler #13220

merged 3 commits into from
May 23, 2025

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 <[email protected]>
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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

3 participants