Nix flamegraph or profiling tool?

I’m having a big closure that takes too much to evaluate. And it has no IFDs. That’s weird.

I’m used to using py-spy to generate flamegraph data that I can feed into to inspect and solve Python apps performance bottlenecks.

Is there anything similar for Nix lang?


I have this zsh function

function nixFunctionCalls {
    local WORKDIR=$(mktemp -d /tmp/nix-fun-calls-XXXXX)
    nix-instantiate --trace-function-calls "$1" -A "$2" 2> $WORKDIR/nix-function-calls.trace 1>/dev/null
    ~/nixgits/nix/contrib/ $WORKDIR/nix-function-calls.trace > $WORKDIR/nix-function-calls.folded
    nix-shell -p flamegraph --run " $WORKDIR/nix-function-calls.folded > $WORKDIR/nix-function-calls.svg"
    echo "$WORKDIR/nix-function-calls.svg"

I use it like so nixFunctionCalls . bash | xargs firefox

here’s the .folded file in speedscope


Is there a flakes alternative to nix-instantiate?

I’m trying your solution and a problem I find is that my .folded file occupies about 59 GB, so I cannot upload it to speedscope, and trying to get a local flamegraph out of it blows my machine.

Is there any other more efficient way to get a flamegraph?

Mine for the nixpkgs bash is only a few mb

I dont know of other ways

From this reply

nix eval --trace-function-calls --raw ".#bash" 2>&1 | cat

For some reason it has to be piped, weird bug.

py-spy has the notion of samples per second. I think that’s how they produce a reasonably-sized dump.

It seems to me that nix just traces every single call, which can amount to many millions when using modules (I have them while using flake-parts and dream2nix in the same project).

It would be nice to be able to have a “samples per second” option for --trace-function-calls.

NIX_SHOW_STATS=1 NIX_COUNT_CALLS=1 could also be helpful

1 Like

Both options seem to dump useful information, but it’s not very human-readable.

Is there any tool that generates some sort of graphic out of that data?

00000000: 0d1b 5b4b 0d1b 5b4b 6675 6e63 7469 6f6e  ..[K..[Kfunction
00000010: 2d74 7261 6365 2065 6e74 6572 6564 20c2  -trace entered .

Nix is putting control chars in stderr for some reason. After cleaning up the control characters and passing it through this very jank AI-generated script, is able to generate svgs.

EDIT: Nevermind, the script doesn’t produce correct results. But it should be easy enough to do.

Adapted to home-manager configuration, made it use nix run to support flakes and inferno for magnitudes faster svg generation:

 home.packages =
        stackCollapse = pkgs.writeTextFile {
          name = "";
          destination = "/bin/";
          text = builtins.readFile (builtins.fetchurl
              url = "";
              sha256 = "sha256:0mi9cf3nx7xjxcrvll1hlkhmxiikjn0w95akvwxs50q270pafbjw";
          executable = true;
        nixFunctionCalls = pkgs.writeShellApplication {
          name = "nixFunctionCalls";
          runtimeInputs = [ stackCollapse pkgs.inferno ];
          text = builtins.readFile ./;
          checkPhase = "";
      [ nixFunctionCalls ];
#!/usr/bin/env zsh

WORKDIR=$(mktemp -d)

nix eval -vvvvvvvvvvvvvvvvvvvv --raw --option trace-function-calls true $1 1>/dev/null 2> $WORKDIR/nix-function-calls.trace $WORKDIR/nix-function-calls.trace > $WORKDIR/nix-function-calls.folded
inferno-flamegraph $WORKDIR/nix-function-calls.folded > $WORKDIR/nix-function-calls.svg
echo "$WORKDIR/nix-function-calls.svg"

thanks a lot for posting it here, can you please explain to me why the pipe xargs command?

like in your example:

nixFunctionCalls . bash | xargs firefox


If you pipe this to xargs firefox it will be the equivalent of firefox ./$WORKDIR/nix-functiona-calls.svg.

1 Like

Some additional ongoing efforts/experiment for a Nix expr evaluation profiler using tracy:

1 Like