splice: defer per-output spliceReal recursion behind genAttrs
`//` forces its rhs to compute the merged keyset, so the original
`// spliceReal (...)` recursed eagerly on every spliced derivation's
outputs even when no specific output (.dev, .doc) was selected.
genAttrs over the known output names with the splice in the
value-thunk defers it: pkg.dev forces, pkg alone doesn't.
Addresses #338231.
Repro:
EXPR='let pkgs = import ./. { localSystem = "x86_64-linux"; crossSystem = "aarch64-linux"; }; in (pkgs.python3.withPackages (ps: [ ps.requests ])).drvPath'
NIX_SHOW_STATS=1 nix-instantiate --eval -E "$EXPR"
drvPath byte-exact (mb82vdkqafg9i8x0makrgxw8xcc4y8lz both ways).
Before:
cpuTime: 0.649
nrFunctionCalls: 651343
nrOpUpdates: 153257
nrOpUpdateValuesCopied: 7908622
nrThunks: 2018744
values: 5061740
sets (bytes): 205342176
gc totalBytes: 320504688
After:
cpuTime: 0.554
nrFunctionCalls: 586266
nrOpUpdates: 125579
nrOpUpdateValuesCopied: 5482176
nrThunks: 1494021
values: 3498806
sets (bytes): 141905680
gc totalBytes: 229067888
This commit is contained in:
@@ -52,12 +52,15 @@ let
|
||||
getOutputs (lib.optionalAttrs success value);
|
||||
getOutputs =
|
||||
value: lib.genAttrs (value.outputs or (lib.optional (value ? out) "out")) (output: value.${output});
|
||||
outputNames = defaultValue.outputs or (lib.optional (defaultValue ? out) "out");
|
||||
outputSplice = spliceReal (
|
||||
mapCrossIndex tryGetOutputs value' // { hostTarget = getOutputs value'.hostTarget; }
|
||||
);
|
||||
in
|
||||
# The derivation along with its outputs, which we recur
|
||||
# on to splice them together.
|
||||
if lib.isDerivation defaultValue then
|
||||
augmentedValue
|
||||
// spliceReal (mapCrossIndex tryGetOutputs value' // { hostTarget = getOutputs value'.hostTarget; })
|
||||
augmentedValue // lib.genAttrs outputNames (out: outputSplice.${out})
|
||||
else if lib.isAttrs defaultValue then
|
||||
spliceReal value'
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user