Jump to content

Nix Profiling: Difference between revisions

From justus.pw Wiki
No edit summary
 
Line 14: Line 14:
$ flamegraph < nix.profile > nix.svg
$ flamegraph < nix.profile > nix.svg
</pre>On my system, this creates a 3.5 MiB SVG file.
</pre>On my system, this creates a 3.5 MiB SVG file.
=== home-manager fonts ===
<code>darwin/fonts.nix</code> curiously becomes part of a long call chain here. I've always wondered why that happens. Here's the source code of <code>darwin/fonts.nix</code>:<pre>
# https://github.com/nix-community/home-manager/blob/2b9504d5a0169d4940a312abe2df2c5658db8de9/modules/targets/darwin/fonts.nix
# SPDX-FileCopyrightText: 2017-2026 Home Manager contributors
# SPDX-License-Identifier: MIT
{
  config,
  lib,
  pkgs,
  ...
}:
let
  homeDir = config.home.homeDirectory;
  fontsEnv = pkgs.buildEnv {
    name = "home-manager-fonts";
    paths = config.home.packages;
    pathsToLink = [ "/share/fonts" ];
  };
  fonts = "${fontsEnv}/share/fonts";
  installDir = "${homeDir}/Library/Fonts/HomeManager";
in
{
  # macOS won't recognize symlinked fonts
  config = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
    home.file."Library/Fonts/.home-manager-fonts-version" = {
      text = "${fontsEnv}";
      onChange = ''
        run mkdir -p ${lib.escapeShellArg installDir}
        run ${pkgs.rsync}/bin/rsync $VERBOSE_ARG -acL --chmod=u+w --delete \
          ${lib.escapeShellArgs [
            "${fonts}/"
            installDir
          ]}
      '';
    };
  };
}
</pre>Specifically line 26 takes a long time to finish:<pre>
${lib.escapeShellArgs [ "${fonts}/" installDir ]}
</pre>Going further up in the call chain, I can see that this is part of the home manager activation script generation. To resolve <code>"${fonts}"</code>, you need to compute <code>config.home.packages</code>. That's why, coincidentally, creating the <code>.home-manager-fonts-version</code> file resolves all packages.

Latest revision as of 07:11, 3 March 2026

Nix-darwin

First, run the following to get a flamegraph:

# This assumes that you've named your nix-darwin configuration
# after your hostname
nix eval --option eval-profiler flamegraph .#darwinConfigurations.$(hostname).system

You should end up with a file called nix.profile:

$ file nix.profile nix.profile: Unicode text, UTF-8 text, with very long lines (1339

Make flamegraph

This zoomed out screenshot of nix.svg shows what kind of image you should expect to come out of the flamegraph tool for a nix eval run on nix-darwin.

Use the flamegraph package to render this nix.profile file to a SVG image:

$ flamegraph < nix.profile > nix.svg

On my system, this creates a 3.5 MiB SVG file.

home-manager fonts

darwin/fonts.nix curiously becomes part of a long call chain here. I've always wondered why that happens. Here's the source code of darwin/fonts.nix:

# https://github.com/nix-community/home-manager/blob/2b9504d5a0169d4940a312abe2df2c5658db8de9/modules/targets/darwin/fonts.nix
# SPDX-FileCopyrightText: 2017-2026 Home Manager contributors
# SPDX-License-Identifier: MIT
{
  config,
  lib,
  pkgs,
  ...
}:

let
  homeDir = config.home.homeDirectory;
  fontsEnv = pkgs.buildEnv {
    name = "home-manager-fonts";
    paths = config.home.packages;
    pathsToLink = [ "/share/fonts" ];
  };
  fonts = "${fontsEnv}/share/fonts";
  installDir = "${homeDir}/Library/Fonts/HomeManager";
in
{
  # macOS won't recognize symlinked fonts
  config = lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
    home.file."Library/Fonts/.home-manager-fonts-version" = {
      text = "${fontsEnv}";
      onChange = ''
        run mkdir -p ${lib.escapeShellArg installDir}
        run ${pkgs.rsync}/bin/rsync $VERBOSE_ARG -acL --chmod=u+w --delete \
          ${lib.escapeShellArgs [
            "${fonts}/"
            installDir
          ]}
      '';
    };
  };
}

Specifically line 26 takes a long time to finish:

${lib.escapeShellArgs [ "${fonts}/" installDir ]}

Going further up in the call chain, I can see that this is part of the home manager activation script generation. To resolve "${fonts}", you need to compute config.home.packages. That's why, coincidentally, creating the .home-manager-fonts-version file resolves all packages.