packages: Optimize ‘all-packages’.

On my laptop, wall-clock time for (all-packages) goes from 27s to 1s.

* gnu/packages.scm (all-packages): Use a hash table to remember visited
packages instead of calling ‘delete-duplicates’ on the final list.

Change-Id: I4aae804656b56ef2095993e91f0572a5891f419f
This commit is contained in:
Ludovic Courtès 2024-12-02 17:06:52 +01:00
parent 12d00767f0
commit 97e7e47d6f
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5

View file

@ -258,18 +258,26 @@ (define all-packages
(mlambda () (mlambda ()
"Return the list of all public packages, including replacements and hidden "Return the list of all public packages, including replacements and hidden
packages, excluding superseded packages." packages, excluding superseded packages."
(delete-duplicates ;; Note: 'fold-packages' never traverses the same package twice but
(fold-packages (lambda (package result) ;; replacements break that (they may or may not be visible to
(match (package-replacement package) ;; 'fold-packages'), hence this hash table to track visited packages.
((? package? replacement) (define visited (make-hash-table))
(cons* replacement package result))
(#f
(cons package result))))
'()
;; Dismiss deprecated packages but keep hidden packages. (fold-packages (lambda (package result)
#:select? (negate package-superseded)) (if (hashq-ref visited package)
eq?))) result
(begin
(hashq-set! visited package #t)
(match (package-replacement package)
((? package? replacement)
(hashq-set! visited replacement #t)
(cons* replacement package result))
(#f
(cons package result))))))
'()
;; Dismiss deprecated packages but keep hidden packages.
#:select? (negate package-superseded))))
(define %package-cache-file (define %package-cache-file
;; Location of the package cache. ;; Location of the package cache.