A look at NixOS/Nixpkgs evaluation times over the years

The option count follows the general trend, but shows none of the spikes.

csv data
Release,Option count
15.09,3373
16.03,3828
16.09,4507
17.03,5445
17.09,6111
18.03,6765
18.09,7617
19.03,8416
19.09,9439
20.03,10096
20.09,11257
21.05,13020
21.11,15003
22.05,16306
22.11,18170
23.05,19981
23.11,21733
24.05,23902
24.11,25682
25.05,28444
2 Likes

I’m pretty sure since we strictly have to merge all options before starting to evaluate the actual config object, this is the biggest linear factor we have in nixpkgs. Even if we figure out the spikes, the general linear trend will continue.

1 Like

Can you share how did you generate the graph? Using the channels.nixos.org option json, I only see 22118 on nixos-unstable, 21972 on 25.05, … :thinking:

release:
let
  pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/${release}.tar.gz") {};
  lib = pkgs.lib;
  moduleList = import "${pkgs.path}/nixos/modules/module-list.nix";
  configEval = import "${pkgs.path}/nixos/lib/eval-config.nix" {
    system = "x86_64-linux";
    modules = moduleList;
  };
in
  builtins.length (map (opt: opt.name) (lib.optionAttrSetToDocList configEval.options))
$ nix eval --impure --expr '(import ./option-count.nix) "nixos-25.05"'
28471

The solution to the growing number of module is clear to me: we have to mandate all modules to have an enable option as an entry point, and only import and evaluate them if they are enabled.

Existing modules loaded that do stuff unconditionally should be rewritten and enabled explicitely, only some exceptions for very basic setup should remain that way.

3 Likes

Thanks! A bit off-topic, but i wonder where this 7k options come from! I see a lot of _module present in the list generated form the nix expr that aren’t present in the options.json.br of the release

yes, not evaluating all modules is a great idea
we have some work to do to get there, though

the pam module is a good example of the work we need to do - the pam module references a ton of other modules
it would be nice if instead the other modules reference pam

Reference to a previous issue about this:

Or minimize the list of modules, as proposed here: [RFC 0022] Minimal module list by edolstra · Pull Request #22 · NixOS/rfcs · GitHub

Having an enable option still requires the module to be parsed and (to some extent) evaluated, so it’s not a scalable approach.

3 Likes

ah… i misinterpreted what @rnhmjoj had written…

i thought he meant what you said :slight_smile: yes, a minimal module list would benefit us in several ways :+1:

i wasn’t aware of that PR… that is awesome!

  • a minimal.nix file containing a list of 185 modules that are required for building the toplevel of an (almost) empty nixos configuration.

This is only the first step and further work is required in order to improve the experience using nixosMinimal

right, an awesome first step! i’m convinced we can go much lower, though - just as a random example

     ./programs/seahorse.nix

currently i’m building my laptop with under 80 nix modules so we can definitely get there, just takes a bunch of refactoring to cleanly separate modules

very exciting work! thanks so much @DavHau and @lassulus for your efforts! :rocket:


note that in this case i defined “nix module” as the result of find ./module-path -type f -name *.nix | wc -l

1 Like

sorry if this is too off-topic, but i thought making imports dependent on config isn’t possible in the module system since it would cause an infinite recursion?

Right, but you can use ${modulesPath}/path/to/module.nix to explicitly import modules. Currently all the modules are imported. The idea here would be to not import them at all. Users would need to explicitly import them.

2 Likes

aghh i thought there is/would be a way to do that without explicitly adding paths i just didn’t know, oh well :cowboy_hat_face:

Yes, importing modules on-demand requires some changes to the module system. I think someone was working on this, but I can’t find a PR. IIRC roberth.

EDIT: I was thinking of this proof of concept, but it looks like it never materialised.

2 Likes
5 Likes

Since @Mic92 mentioned the flamegraphs in the nightly nix versions, I decided to make some!
I decided not to put the logs in the repo since they were too big and I didn’t feel like compressing it, but if you just drop into the devshell and run uv run nixpkgs-profiler.py, the logs will be generated.

The flamegraphs are in outputs/flamegraphs/*.svg.
Note that you need to drop into the devshell to have the logs generate, since the python script shells out to the nix version in PATH, and I was too lazy to create a derivation.
This might have some flake overhead compared to the original graphs, but I doubt it’ll be too big. I haven’t really looked at it at all.