summary refs log tree commit diff
diff options
context:
space:
mode:
authorRussell O'Connor <roconnor@theorem.ca>2014-09-28 09:39:39 -0400
committerRussell O'Connor <roconnor@theorem.ca>2014-09-28 09:39:39 -0400
commit94c6af494a8c7d7a8a6f516312e4f848c1a62ed4 (patch)
tree8987d8f26931955ee56b7f49f95c51d2769cfeb4
parent63280c511effbe1c7d6892304242aa094dc56bae (diff)
downloadnixpkgs-94c6af494a8c7d7a8a6f516312e4f848c1a62ed4.tar
nixpkgs-94c6af494a8c7d7a8a6f516312e4f848c1a62ed4.tar.gz
nixpkgs-94c6af494a8c7d7a8a6f516312e4f848c1a62ed4.tar.bz2
nixpkgs-94c6af494a8c7d7a8a6f516312e4f848c1a62ed4.tar.lz
nixpkgs-94c6af494a8c7d7a8a6f516312e4f848c1a62ed4.tar.xz
nixpkgs-94c6af494a8c7d7a8a6f516312e4f848c1a62ed4.tar.zst
nixpkgs-94c6af494a8c7d7a8a6f516312e4f848c1a62ed4.zip
Exponentially reduce computation time needed for replace-dependency by using memoization.
This patch makes two changes.

(1) It memoizes the computation of dependsOnOld.
(2) It replaces rewrittenDerivations with a similar memoized table rewriteMemo.

This prevents the entire tree of run-time dependencies from being traversed and instead only traverses the graph of run-time dependencies.
In the case of deep dependency changes (such as changing one's bash version for an entire NixOS system) this can lead to an exponential speedup in processing time
because shared dependencies are no longer traversed multiple times.

This patch isn't quite derivation-per-derivation equivalent to the original computation.
There are two immaterial differences.

(1) The previous version would always call upon sed to replace oldDependency with newDependency even when the store object being updated doesn't directly depend on
oldDependency.
The new version only replaceds oldDependency with newDependency when the store object being updated actually directly depends on oldDependency (which means there is
actually a hash to replace).
(2) The previous version would list the old store object as a source input of the new store object, *except* for the root derivation being updated.  Because the
root derivation being updated has its actual derivation avaiable the previous verions would make the updated root derivation depend on the old derivation as a
derivation input instead of a source input.
The new version always lists the old store object as a source input, including the root derivation.
-rw-r--r--pkgs/build-support/replace-dependency.nix26
1 files changed, 14 insertions, 12 deletions
diff --git a/pkgs/build-support/replace-dependency.nix b/pkgs/build-support/replace-dependency.nix
index 098637b4f9b..ed65b9dad1d 100644
--- a/pkgs/build-support/replace-dependency.nix
+++ b/pkgs/build-support/replace-dependency.nix
@@ -49,8 +49,13 @@ let
 
   referencesOf = drv: getAttr (discard (toString drv)) references;
 
-  dependsOnOld = drv: elem oldStorepath (referencesOf drv) ||
-    any dependsOnOld (referencesOf drv);
+  dependsOnOldMemo = listToAttrs (map
+    (drv: { name = discard (toString drv);
+            value = elem oldStorepath (referencesOf drv) ||
+                    any dependsOnOld (referencesOf drv);
+          }) (builtins.attrNames references));
+
+  dependsOnOld = drv: getAttr (discard (toString drv)) dependsOnOldMemo;
 
   drvName = drv:
     discard (substring 33 (stringLength (builtins.baseNameOf drv)) (builtins.baseNameOf drv));
@@ -65,15 +70,12 @@ let
 
   rewrittenDeps = listToAttrs [ {name = discard (toString oldDependency); value = newDependency;} ];
 
-  rewrittenDerivations = drv:
-    if dependsOnOld drv
-      then listToAttrs [ {
-        name = discard (toString drv);
+  rewriteMemo = listToAttrs (map
+    (drv: { name = discard (toString drv);
+            value = rewriteHashes (builtins.storePath drv)
+              (filterAttrs (n: v: builtins.elem (builtins.storePath (discard (toString n))) (referencesOf drv)) rewriteMemo);
+          })
+    (filter dependsOnOld (builtins.attrNames references))) // rewrittenDeps;
 
-        value = rewriteHashes drv (rewrittenDeps // (fold (drv: acc:
-          (rewrittenDerivations drv) // acc
-        ) {} (referencesOf drv)));
-      } ]
-      else {};
 in assert (stringLength (drvName (toString oldDependency)) == stringLength (drvName (toString newDependency)));
-getAttr (discard (toString drv)) (rewrittenDerivations drv)
+getAttr (discard (toString drv)) rewriteMemo