Archived
1
0
Fork 0

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:
Ludovic Courtès 2020-06-06 18:46:49 +02:00
parent 22fdca91a9
commit 58bb833365
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5

View file

@ -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))