pull: Compile files in parallel.
* guix/scripts/pull.scm (unpack)[builder](compile-file*): Remove. (call-with-process, p-for-each): New procedures. Use them to compile files in parallel.
This commit is contained in:
parent
0c2e1dd45d
commit
ca6c4fa190
|
@ -59,29 +59,49 @@ files."
|
||||||
(gcrypt (assoc-ref %build-inputs "gcrypt"))
|
(gcrypt (assoc-ref %build-inputs "gcrypt"))
|
||||||
(tarball (assoc-ref %build-inputs "tarball")))
|
(tarball (assoc-ref %build-inputs "tarball")))
|
||||||
|
|
||||||
(define* (compile-file* file #:key output-file (opts '()))
|
(define (call-with-process thunk)
|
||||||
;; Like 'compile-file', but in a separate process, to work around
|
;; Run THUNK in a separate process that will return 0 if THUNK
|
||||||
;; <http://bugs.gnu.org/15602> (FIXME). This ensures correctness,
|
;; terminates normally, and 1 if an exception is raised.
|
||||||
;; but is overly conservative and very slow. The solution
|
|
||||||
;; initially implemented (and described in the bug above) was
|
|
||||||
;; slightly faster but consumed memory proportional to the number
|
|
||||||
;; of modules, which quickly became unacceptable.
|
|
||||||
(match (primitive-fork)
|
(match (primitive-fork)
|
||||||
(0
|
(0
|
||||||
(catch #t
|
(catch #t
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(compile-file file
|
(thunk)
|
||||||
#:output-file output-file
|
|
||||||
#:opts opts)
|
|
||||||
(primitive-exit 0))
|
(primitive-exit 0))
|
||||||
(lambda (key . args)
|
(lambda (key . args)
|
||||||
(print-exception (current-error-port) #f key args)
|
(print-exception (current-error-port) #f key args)
|
||||||
(primitive-exit 1))))
|
(primitive-exit 1))))
|
||||||
(pid
|
(pid
|
||||||
(match (waitpid pid)
|
#t)))
|
||||||
((_ . status)
|
|
||||||
(unless (zero? (status:exit-val status))
|
(define (p-for-each proc lst)
|
||||||
(error "failed to compile file" file status)))))))
|
;; Invoke PROC for each element of LST in a separate process.
|
||||||
|
;; Raise an error if one of the processes exit with non-zero.
|
||||||
|
(define (wait-for-one-process)
|
||||||
|
(match (waitpid WAIT_ANY)
|
||||||
|
((_ . status)
|
||||||
|
(unless (zero? (status:exit-val status))
|
||||||
|
(error "process failed" proc status)))))
|
||||||
|
|
||||||
|
(define max-processes
|
||||||
|
(current-processor-count))
|
||||||
|
|
||||||
|
(let loop ((lst lst)
|
||||||
|
(running 0))
|
||||||
|
(match lst
|
||||||
|
(()
|
||||||
|
(or (zero? running)
|
||||||
|
(begin
|
||||||
|
(wait-for-one-process)
|
||||||
|
(loop lst (- running 1)))))
|
||||||
|
((head . tail)
|
||||||
|
(if (< running max-processes)
|
||||||
|
(begin
|
||||||
|
(call-with-process (cut proc head))
|
||||||
|
(loop tail (+ running 1)))
|
||||||
|
(begin
|
||||||
|
(wait-for-one-process)
|
||||||
|
(loop lst (- running 1))))))))
|
||||||
|
|
||||||
(setenv "PATH" (string-append tar "/bin:" gzip "/bin"))
|
(setenv "PATH" (string-append tar "/bin:" gzip "/bin"))
|
||||||
|
|
||||||
|
@ -113,19 +133,24 @@ files."
|
||||||
(set! %load-path (cons out %load-path))
|
(set! %load-path (cons out %load-path))
|
||||||
(set! %load-compiled-path (cons out %load-compiled-path))
|
(set! %load-compiled-path (cons out %load-compiled-path))
|
||||||
|
|
||||||
;; Compile the .scm files.
|
;; Compile the .scm files. Do that in independent processes, à la
|
||||||
(for-each (lambda (file)
|
;; 'make -j', to work around <http://bugs.gnu.org/15602> (FIXME).
|
||||||
(when (string-suffix? ".scm" file)
|
;; This ensures correctness, but is overly conservative and slow.
|
||||||
|
;; The solution initially implemented (and described in the bug
|
||||||
|
;; above) was slightly faster but consumed memory proportional to the
|
||||||
|
;; number of modules, which quickly became unacceptable.
|
||||||
|
(p-for-each (lambda (file)
|
||||||
(let ((go (string-append (string-drop-right file 4)
|
(let ((go (string-append (string-drop-right file 4)
|
||||||
".go")))
|
".go")))
|
||||||
(format (current-error-port)
|
(format (current-error-port)
|
||||||
"compiling '~a'...~%" file)
|
"compiling '~a'...~%" file)
|
||||||
(compile-file* file
|
(compile-file file
|
||||||
#:output-file go
|
#:output-file go
|
||||||
#:opts
|
#:opts
|
||||||
%auto-compilation-options))))
|
%auto-compilation-options)))
|
||||||
|
|
||||||
(find-files out "\\.scm"))
|
(filter (cut string-suffix? ".scm" <>)
|
||||||
|
(find-files out "\\.scm")))
|
||||||
|
|
||||||
;; Remove the "fake" (guix config).
|
;; Remove the "fake" (guix config).
|
||||||
(delete-file (string-append out "/guix/config.scm"))
|
(delete-file (string-append out "/guix/config.scm"))
|
||||||
|
|
Loading…
Reference in New Issue