profiles: Fix pathological performance of 'manifest-transitive-entries'.

For packages with lots of propagated inputs,
'manifest-transitive-entries', as called from 'check-for-collisions',
would exhibit pathological behavior.  For example, "guix install cl-ana"
wouldn't complete in 1mn; now, it's down to 20s.

The issue was that manifest entries would never be 'equal?' due to the
delayed field in <manifest-entry>.

* guix/profiles.scm (manifest-transitive-entries): Use a vhash instead
of a set.  Use 'manifest-entry=?' instead of 'equal?' when checking for
equality.
This commit is contained in:
Ludovic Courtès 2020-06-14 14:51:02 +02:00
parent 20d9034cc5
commit 9acac9f9c6
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5

View File

@ -41,7 +41,6 @@
#:use-module (guix modules) #:use-module (guix modules)
#:use-module (guix monads) #:use-module (guix monads)
#:use-module (guix store) #:use-module (guix store)
#:use-module (guix sets)
#:use-module (ice-9 vlist) #:use-module (ice-9 vlist)
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:use-module (ice-9 regex) #:use-module (ice-9 regex)
@ -260,17 +259,17 @@ field."
recursively." recursively."
(let loop ((entries (manifest-entries manifest)) (let loop ((entries (manifest-entries manifest))
(result '()) (result '())
(visited (set))) ;compare with 'equal?' (visited vlist-null)) ;compare with 'manifest-entry=?'
(match entries (match entries
(() (()
(reverse result)) (reverse result))
((head . tail) ((head . tail)
(if (set-contains? visited head) (if (vhash-assoc head visited manifest-entry=?)
(loop tail result visited) (loop tail result visited)
(loop (append (manifest-entry-dependencies head) (loop (append (manifest-entry-dependencies head)
tail) tail)
(cons head result) (cons head result)
(set-insert head visited))))))) (vhash-cons head #t visited)))))))
(define (profile-manifest profile) (define (profile-manifest profile)
"Return the PROFILE's manifest." "Return the PROFILE's manifest."