summary refs log tree commit diff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2016-03-04 23:10:28 +0100
committerLudovic Courtès <ludo@gnu.org>2016-03-05 00:19:10 +0100
commitd4da602e4c28d704ee04ec57887fa14b134c7ebb (patch)
tree7242ce7745ceedd28401f8698636dc523c8f0212
parentfcadd9ff9dfd57c4d386287477e665d4efe9090d (diff)
downloadguix-d4da602e4c28d704ee04ec57887fa14b134c7ebb.tar.gz
grafts: Memoize intermediate results in 'cumulative-grafts'.
The time for:

  guix build inkscape -n --no-substitutes

goes down by 30% (in the presence of 3 replacements among all the
packages.)

* guix/grafts.scm (cumulative-grafts): Turn into a monadic procedure in
%STATE-MONAD.  Use the current state as a derivation-to-graft cache.
(graft-derivation): Call 'cumulative-grafts' within 'run-with-state'.
-rw-r--r--guix/grafts.scm54
1 files changed, 35 insertions, 19 deletions
diff --git a/guix/grafts.scm b/guix/grafts.scm
index eca0a9fcad..af469575db 100644
--- a/guix/grafts.scm
+++ b/guix/grafts.scm
@@ -217,7 +217,10 @@ available."
   "Augment GRAFTS with additional grafts resulting from the application of
 GRAFTS to the dependencies of DRV; REFERENCES must be a one-argument procedure
 that returns the list of references of the store item it is given.  Return the
-resulting list of grafts."
+resulting list of grafts.
+
+This is a monadic procedure in %STATE-MONAD where the state is a vhash mapping
+derivations to the corresponding set of grafts."
   (define (dependency-grafts item)
     (let-values (((drv output) (item->deriver store item)))
       (if drv
@@ -225,23 +228,34 @@ resulting list of grafts."
                              #:outputs (list output)
                              #:guile guile
                              #:system system)
-          grafts)))
+          (state-return grafts))))
+
+  (define (return/cache cache value)
+    (mbegin %store-monad
+      (set-current-state (vhash-consq drv value cache))
+      (return value)))
 
-  ;; TODO: Memoize.
-  (match (non-self-references references drv outputs)
-    (()                                           ;no dependencies
-     grafts)
-    (deps                                         ;one or more dependencies
-     (let* ((grafts  (delete-duplicates (append-map dependency-grafts deps)
-                                        eq?))
-            (origins (map graft-origin-file-name grafts)))
-       (if (find (cut member <> deps) origins)
-           (let ((new (graft-derivation/shallow store drv grafts
-                                                #:guile guile
-                                                #:system system)))
-             (cons (graft (origin drv) (replacement new))
-                   grafts))
-           grafts)))))
+  (mlet %state-monad ((cache (current-state)))
+    (match (vhash-assq drv cache)
+      ((_ . grafts)                               ;hit
+       (return grafts))
+      (#f                                         ;miss
+       (match (non-self-references references drv outputs)
+         (()                                      ;no dependencies
+          (return/cache cache grafts))
+         (deps                                    ;one or more dependencies
+          (mlet %state-monad ((grafts (mapm %state-monad dependency-grafts deps))
+                              (cache  (current-state)))
+            (let* ((grafts  (delete-duplicates (concatenate grafts) equal?))
+                   (origins (map graft-origin-file-name grafts)))
+              (if (find (cut member <> deps) origins)
+                  (let* ((new    (graft-derivation/shallow store drv grafts
+                                                           #:guile guile
+                                                           #:system system))
+                         (grafts (cons (graft (origin drv) (replacement new))
+                                       grafts)))
+                    (return/cache cache grafts))
+                  (return/cache cache grafts))))))))))
 
 (define* (graft-derivation store drv grafts
                            #:key (guile (%guile-for-build))
@@ -256,8 +270,10 @@ DRV itself to refer to those grafted dependencies."
   (define references
     (references-oracle store drv))
 
-  (match (cumulative-grafts store drv grafts references
-                            #:guile guile #:system system)
+  (match (run-with-state
+             (cumulative-grafts store drv grafts references
+                                #:guile guile #:system system)
+           vlist-null)                            ;the initial cache
     ((first . rest)
      ;; If FIRST is not a graft for DRV, it means that GRAFTS are not
      ;; applicable to DRV and nothing needs to be done.