Unverified Commit 363ae292 authored by zimbatm's avatar zimbatm Committed by Yvan Sraka
Browse files

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
parent 466ceb6b
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -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