grafts: Improve performance for derivations with many inputs.
Partly fixes <https://bugs.gnu.org/41702>. Reported by Lars-Dominik Braun <ldb@leibniz-psychology.org>. Previously we'd potentially traverse the same sub-graph of DEPS several times. With this patch, command: guix environment --ad-hoc r-learnr --search-paths goes from 11.3s to 4.6s. * guix/grafts.scm (reference-origin): Rename to... (reference-origins): ... this. Change 'item' parameter to 'items'. [lookup-derivers]: New procedure. (cumulative-grafts)[dependency-grafts]: Change 'item' to 'items' and use 'reference-origins'. Remove 'mapm' around 'dependency-grafts' call.
This commit is contained in:
		
							parent
							
								
									22fdca91a9
								
							
						
					
					
						commit
						58bb833365
					
				
					 1 changed files with 52 additions and 33 deletions
				
			
		| 
						 | 
					@ -20,10 +20,12 @@
 | 
				
			||||||
  #:use-module (guix store)
 | 
					  #:use-module (guix store)
 | 
				
			||||||
  #:use-module (guix monads)
 | 
					  #:use-module (guix monads)
 | 
				
			||||||
  #:use-module (guix records)
 | 
					  #:use-module (guix records)
 | 
				
			||||||
 | 
					  #:use-module (guix combinators)
 | 
				
			||||||
  #:use-module (guix derivations)
 | 
					  #:use-module (guix derivations)
 | 
				
			||||||
  #:use-module ((guix utils) #:select (%current-system))
 | 
					  #:use-module ((guix utils) #:select (%current-system))
 | 
				
			||||||
  #:use-module (guix sets)
 | 
					  #:use-module (guix sets)
 | 
				
			||||||
  #:use-module (srfi srfi-1)
 | 
					  #:use-module (srfi srfi-1)
 | 
				
			||||||
 | 
					  #:use-module (srfi srfi-11)
 | 
				
			||||||
  #:use-module (srfi srfi-9 gnu)
 | 
					  #:use-module (srfi srfi-9 gnu)
 | 
				
			||||||
  #:use-module (srfi srfi-26)
 | 
					  #:use-module (srfi srfi-26)
 | 
				
			||||||
  #:use-module (srfi srfi-34)
 | 
					  #:use-module (srfi srfi-34)
 | 
				
			||||||
| 
						 | 
					@ -183,31 +185,46 @@ references."
 | 
				
			||||||
           (set-current-state (vhash-cons key result cache))
 | 
					           (set-current-state (vhash-cons key result cache))
 | 
				
			||||||
           (return result)))))))
 | 
					           (return result)))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define (reference-origin drv item)
 | 
					(define (reference-origins drv items)
 | 
				
			||||||
  "Return the derivation/output pair among the inputs of DRV, recursively,
 | 
					  "Return the derivation/output pairs among the inputs of DRV, recursively,
 | 
				
			||||||
that produces ITEM.  Return #f if ITEM is not produced by a derivation (i.e.,
 | 
					that produce ITEMS.  Elements of ITEMS not produced by a derivation (i.e.,
 | 
				
			||||||
it's a content-addressed \"source\"), or if it's not produced by a dependency
 | 
					it's a content-addressed \"source\"), or not produced by a dependency of DRV,
 | 
				
			||||||
of DRV."
 | 
					have no corresponding element in the resulting list."
 | 
				
			||||||
 | 
					  (define (lookup-derivers drv result items)
 | 
				
			||||||
 | 
					    ;; Return RESULT augmented by all the drv/output pairs producing one of
 | 
				
			||||||
 | 
					    ;; ITEMS, and ITEMS stripped of matching items.
 | 
				
			||||||
 | 
					    (fold2 (match-lambda*
 | 
				
			||||||
 | 
					             (((output . file) result items)
 | 
				
			||||||
 | 
					              (if (member file items)
 | 
				
			||||||
 | 
					                  (values (alist-cons drv output result)
 | 
				
			||||||
 | 
					                          (delete file items))
 | 
				
			||||||
 | 
					                  (values result items))))
 | 
				
			||||||
 | 
					           result items
 | 
				
			||||||
 | 
					           (derivation->output-paths drv)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ;; Perform a breadth-first traversal of the dependency graph of DRV in
 | 
					  ;; Perform a breadth-first traversal of the dependency graph of DRV in
 | 
				
			||||||
  ;; search of the derivation that produces ITEM.
 | 
					  ;; search of the derivations that produce ITEMS.
 | 
				
			||||||
  (let loop ((drv (list drv))
 | 
					  (let loop ((drv (list drv))
 | 
				
			||||||
 | 
					             (items items)
 | 
				
			||||||
 | 
					             (result '())
 | 
				
			||||||
             (visited (setq)))
 | 
					             (visited (setq)))
 | 
				
			||||||
    (match drv
 | 
					    (match drv
 | 
				
			||||||
      (()
 | 
					      (()
 | 
				
			||||||
       #f)
 | 
					       result)
 | 
				
			||||||
      ((drv . rest)
 | 
					      ((drv . rest)
 | 
				
			||||||
       (if (set-contains? visited drv)
 | 
					       (cond ((null? items)
 | 
				
			||||||
           (loop rest visited)
 | 
					              result)
 | 
				
			||||||
           (let ((inputs (derivation-inputs drv)))
 | 
					             ((set-contains? visited drv)
 | 
				
			||||||
             (or (any (lambda (input)
 | 
					              (loop rest items result visited))
 | 
				
			||||||
                        (let ((drv (derivation-input-derivation input)))
 | 
					             (else
 | 
				
			||||||
                          (any (match-lambda
 | 
					              (let*-values (((inputs)
 | 
				
			||||||
                                 ((output . file)
 | 
					                             (map derivation-input-derivation
 | 
				
			||||||
                                  (and (string=? file item)
 | 
					                                  (derivation-inputs drv)))
 | 
				
			||||||
                                       (cons drv output))))
 | 
					                            ((result items)
 | 
				
			||||||
                               (derivation->output-paths drv))))
 | 
					                             (fold2 lookup-derivers
 | 
				
			||||||
                      inputs)
 | 
					                                    result items inputs)))
 | 
				
			||||||
                 (loop (append rest (map derivation-input-derivation inputs))
 | 
					                (loop (append rest inputs)
 | 
				
			||||||
 | 
					                      items result
 | 
				
			||||||
                      (set-insert drv visited)))))))))
 | 
					                      (set-insert drv visited)))))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(define* (cumulative-grafts store drv grafts
 | 
					(define* (cumulative-grafts store drv grafts
 | 
				
			||||||
| 
						 | 
					@ -233,25 +250,27 @@ derivations to the corresponding set of grafts."
 | 
				
			||||||
      (_
 | 
					      (_
 | 
				
			||||||
       #f)))
 | 
					       #f)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (define (dependency-grafts item)
 | 
					  (define (dependency-grafts items)
 | 
				
			||||||
    (match (reference-origin drv item)
 | 
					    (mapm %store-monad
 | 
				
			||||||
 | 
					          (lambda (drv+output)
 | 
				
			||||||
 | 
					            (match drv+output
 | 
				
			||||||
              ((drv . output)
 | 
					              ((drv . output)
 | 
				
			||||||
       ;; If GRAFTS already contains a graft from DRV, do not override it.
 | 
					               ;; If GRAFTS already contains a graft from DRV, do not
 | 
				
			||||||
 | 
					               ;; override it.
 | 
				
			||||||
               (if (find (cut graft-origin? drv <>) grafts)
 | 
					               (if (find (cut graft-origin? drv <>) grafts)
 | 
				
			||||||
                   (state-return grafts)
 | 
					                   (state-return grafts)
 | 
				
			||||||
                   (cumulative-grafts store drv grafts
 | 
					                   (cumulative-grafts store drv grafts
 | 
				
			||||||
                                      #:outputs (list output)
 | 
					                                      #:outputs (list output)
 | 
				
			||||||
                                      #:guile guile
 | 
					                                      #:guile guile
 | 
				
			||||||
                              #:system system)))
 | 
					                                      #:system system)))))
 | 
				
			||||||
      (#f
 | 
					          (reference-origins drv items)))
 | 
				
			||||||
       (state-return grafts))))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  (with-cache (cons (derivation-file-name drv) outputs)
 | 
					  (with-cache (cons (derivation-file-name drv) outputs)
 | 
				
			||||||
    (match (non-self-references store drv outputs)
 | 
					    (match (non-self-references store drv outputs)
 | 
				
			||||||
      (()                                         ;no dependencies
 | 
					      (()                                         ;no dependencies
 | 
				
			||||||
       (return grafts))
 | 
					       (return grafts))
 | 
				
			||||||
      (deps                                       ;one or more dependencies
 | 
					      (deps                                       ;one or more dependencies
 | 
				
			||||||
       (mlet %state-monad ((grafts (mapm %state-monad dependency-grafts deps)))
 | 
					       (mlet %state-monad ((grafts (dependency-grafts deps)))
 | 
				
			||||||
         (let ((grafts (delete-duplicates (concatenate grafts) equal?)))
 | 
					         (let ((grafts (delete-duplicates (concatenate grafts) equal?)))
 | 
				
			||||||
           (match (filter (lambda (graft)
 | 
					           (match (filter (lambda (graft)
 | 
				
			||||||
                            (member (graft-origin-file-name graft) deps))
 | 
					                            (member (graft-origin-file-name graft) deps))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Reference in a new issue