lib/modules: reduce allocations in evalModules and mergeModules

- When `evalModules` is called without deprecated `args`/`check` parameters (the common case), avoid `modules ++ []` which copies the entire module list for no reason.
- `collectModules` was calling `collectStructuredModules` twice with identical arguments — once for `filterModules` and once for `toGraph`. Share the result via a `let` binding.
- Replace `zipAttrsWith (n: v: v)` with `zipAttrs`
- Replace `concatMap` with `filter`+`map` in `filterOverrides'`

NixOS minimal eval improvement: -5.0% list_concats, -1.2%
nrFunctionCalls, -0.7% nrThunks, -1.0% envs, -1.5% list_bytes.
This commit is contained in:
Ben Siraphob
2026-04-14 10:34:20 -07:00
parent 67c22bba37
commit b787ee3d40

View File

@@ -589,6 +589,8 @@ let
in
modulesPath: initialModules: args: {
modules = filterModules modulesPath (collectStructuredModules unknownModule "" initialModules args);
# Intentionally not shared with `modules` above: this allows `collected`
# to be garbage collected after `filterModules` returns.
graph = toGraph modulesPath (collectStructuredModules unknownModule "" initialModules args);
};
@@ -783,7 +785,7 @@ let
prefix: modules: configs:
let
# an attrset 'name' => list of submodules that declare name.
declsByName = zipAttrsWith (n: v: v) (
declsByName = zipAttrs (
map (
module:
let
@@ -838,7 +840,7 @@ let
) checkedConfigs
);
# extract the definitions for each loc
rawDefinitionsByName = zipAttrsWith (n: v: v) (
rawDefinitionsByName = zipAttrs (
map (
module:
mapAttrs (n: value: {
@@ -1439,7 +1441,7 @@ let
def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def;
in
{
values = concatMap (def: if getPrio def == highestPrio then [ (strip def) ] else [ ]) defs;
values = map strip (filter (def: getPrio def == highestPrio) defs);
inherit highestPrio;
};