-
-
Notifications
You must be signed in to change notification settings - Fork 158
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
[RFC 0022] Minimal module list #22
Conversation
This seems like a very bad change in terms of usability, especially for "normal" users, in return for faster evaluations that favor the power users. The 1%! 😋 Being able to just set I'm optimistic that we can accomplish your goals (and wow these changes really do reduce resource usage!) without negatively impacting normal use. My other concern is that in the current world all modules are evaluated -- which kinda means they are always evaluate-able. Maybe I overestimate the benefit of that, but it seems this change might make it easier for modules to bitrot badly without anyone noticing. There is the related problem of backwards compatibility as well, I suppose. One solution to most of these is to make your suggested changes "under the hood" but by default still include "all" modules. Unless user indicates they want to "roll their own"-- which many may elect to do, myself included-- with a flag or something in the configuration? Finally I would say that I don't see a fundamental reason including all modules should be so bad, since (for an example) an order of magnitude improvement in the evaluator would very likely eliminate this problem almost entirely. There just aren't that many modules and the growth is linearish. I'm not saying we can achieve that sort of improvement, but I think it's a touch misleading to say evaluating all modules is inevitably a problem-- there's not an unlimited supply of useful modules. But improving the evaluator is really hard. This looks like good cleanup we should do anyway, and practically speaking does show huge improvements that are certainly worth pursuing. Hopefully we can have our 🎂 and eat it too. |
Whoops I see
Which is where I ended up too. Hmm, well I'll re-read and think some more. :) |
module defines an option declared in another. For example, | ||
`network-interfaces.nix` sets `virtualisation.vswitch`, requiring | ||
`virtualisation/openvswitch.nix` to be included even when | ||
`networking.vswitches = {}`. It's not clear what the best way is to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about a hybrid where we keep all potential dependencies in module-list.nix
but the rest is included explicitly? E.g. virtualisation.vswitch
would be in, but services.uptimed
would not). I did a super quick estimation by
- finding configurations:
git grep -h "^ cfg = config." | sort | uniq | head
- sampling ~20 items at random like below to see whether they are used as a dependency
git grep services.redmine
And my guess is that <10% of modules are dependencies for other modules.
The major downsides IMO would be inconsistency (some modules are special) and discoverability (contributors need to know that they have to elevate their dependencies when they add them).
I think that unresolved question @teh mentions raises an interesting point: we could do something like this for isolating modules rather than performance, an argument I find more compelling. The module system currently allowing anything to affect anything else is great for easily adding functionality in new modules, it's not so good for reasoning about the interactions between modules after the fact. Perhaps the tension between flexibility and encapsulation is fundamental, and given the general insanity of the underlying Unix userland itself, the module system errs in the right direction. But I'd want to make sure of that first. |
Could conditional imports be possible instead ? So far there is no |
@Ericson2314 Yes, the fundamental flaw of the module system is that any module can change anything (i.e. they violate the principle of least authority). But replacing the module system with a more functional approach is a much more significant undertaking which is out of scope of this RFC. @dtzWill Is writing |
The alternative is to continue with the current approach of including | ||
every module in `module-list.nix`. However, it's clear that this | ||
approach does not scale. Performance improvements to the evaluator can | ||
only delay the module apocalypse. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How much room for optimization is there in the nix evaluator? I remember while profiling ruby that stat()
and open()
were a big part of the interpreter startup.
| --------------------------- | -------- | --------- | | ||
| 17.09 | 73.7 | 6470 | | ||
| 17.09 minimal | 19.5 | 2577 | | ||
| 17.09 minimal + memoisation | 12.5 | 1532 | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
12 seconds is actually quite reasonable compared to building pretty much anything else. Is it not possible to prepare the system outputs through Hydra?
# Drawbacks | ||
[drawbacks]: #drawbacks | ||
|
||
... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see two major drawbacks:
If nixpkgs is loaded using fetchFromGitHub then the <nixpkgs/...>
notation doesn't work. It has to be pkgs.path + "/..."
. This causes issues for composability of nixpkgs itself.
How will the https://nixos.org/nixos/options.html# list be populated?
Would it not be possible to make the module loading lazy?
Such as That would add a bit of evaluation overhead for each module but since most modules are not used it would lower to overall evaluation time. There is only a subset of modules that use the |
If that leads to a very well maintained list of core modules and a secondary list of community managed modules, that could be a good step.
That might lead to strange patterns, where enabling some module could lead to a type error in another part of the repo. Since module errors already are very much non-local that could lead to a major decrease in usability. |
all modules. | ||
|
||
* Most `enable` options defaults should be changed to `true`, so that | ||
including a module activates it automatically. (But see below.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would that work with all-modules.nix
? Having all modules enabled by default wouldn't be very compatible...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, all-modules.nix
would also have to disable those modules by setting their enable
option to false.
All the lazy modules would be enabled during document generation, which would surface that kind of incompatibility. Another thing I would like to see happen is to enforce the namespace extension such as a module can only define new config option below a specific namespace. |
I agree we should not import all modules, so I definitely like to see this.
Not sure whether that is possible, but we could move that flag out:
This is basically just Each module can define a |
By the way, if there were a large list of |
Since everything is global it's currently not possible to make imports conditional. The fact that a module is imported could influence the condition so you end up with recursion. |
Also, a giant list of |
... | ||
|
||
# Drawbacks | ||
[drawbacks]: #drawbacks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One drawback is that it will freeze our file hierarchy as we don't have a mechanism in place to notify of file renames. Each rename would have to also include a symlink from the original to new place.
A good start would be to map the nixos options back to a file hierarchy. For example:
Once we have that in place we could then create a new module system under a new |
This RFC should be postponed until we have the flake mechanism, because that should make it a lot easier to have dependencies on other repos and split up Nixpkgs. Most modules in NixOS could be moved into separate flakes living in their own repositories. So for example, my NixOS configuration would have a dependency on the |
Let's close this RFC then as it will take a different form once flake is implemented |
👍 |
What is the 'flakes' mechanism? Could it be linked here for people getting on this page later? |
This seems to be where the actual info is. |
This pull request has been mentioned on Nix community. There might be relevant details there: https://discourse.nixos.org/t/minimal-set-of-nixos-modules/2328/2 |
This pull request has been mentioned on Nix community. There might be relevant details there: https://discourse.nixos.org/t/writing-modules-for-nur/2520/6 |
Seems like there is some work in this area over at https://github.com/tweag/nix/blob/flakes/src/libexpr/primops/flake.hh :-) |
more information about the ongoing implementation of Nix flakes: https://gist.github.com/edolstra/40da6e3a4d4ee8fd019395365e0772e7 |
I've done some work on this in NixOS/nixpkgs#148456, adding the flexibility to use part of NixOS for configuring images and allowing to avoid the messy nixpkgs invocation module for example. NixOS/nixpkgs#153211 is the first non-PoC PR. It allows experimentation with a minimal module list, refactoring towards the goal of this RFC, without breaking regular NixOS. |
NixOS/nixpkgs#155892 unit-tests |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/restructuring-nixos-to-work-without-systemd-e-g-with-sysvinit/21298/42 |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2023-08-08-nixpkgs-architecture-team-meeting-42/31454/1 |
A WIP proposal for reducing NixOS evaluation time by getting rid of our giant
module-list.nix
.Rendered: https://github.com/edolstra/rfcs/blob/minimal-module-list/rfcs/0022-minimal-module-list.md