Subject: Re: bug#74748: Constructor created by define-configuration is slow (>25s) when many fields are defined

From: Ludovic Courtès <[email-masked]>
Date: Tue, 24 Dec 2024 15:38:30 +0100

Hi,

Tomas Volf <[email-masked]> skribis:

> I am writing a configuration for mpv and hit an issue of the generated
> constructor (`home-mpv-configuration') is extremely slow.  While the
> almost 800 fields is unusually high, initializing the instances of the
> record should *not* take almost 30 seconds.  The full file is attached
> to this email (as `mpv.scm').

AFAICS, time is spent in one of the compilation steps:

--8<---------------cut here---------------start------------->8---
scheme@(gnu home services mpv)> ,o interp #t
scheme@(gnu home services mpv)> ,t (lambda () (mpv-profile-configuration))
$13 = #<procedure 7f6ed3796700 at ice-9/eval.scm:330:13 ()>
;; 0.376347s real time, 0.375402s run time.  0.000000s spent in GC.
scheme@(gnu home services mpv)> ,o interp #f
scheme@(gnu home services mpv)> ,t (lambda () (mpv-profile-configuration))
$14 = #<procedure 7f6ec32088f8 at <unknown port>:40:3 ()>
;; 11.149828s real time, 12.052915s run time.  1.581736s spent in GC.
scheme@(gnu home services mpv)> ,t (->bool (macroexpand '(mpv-profile-configuration)))
$15 = #t
;; 0.373865s real time, 0.372698s run time.  0.000000s spent in GC.
--8<---------------cut here---------------end--------------->8---

If we look more closely, it’s the optimizing compiler that takes time;
the baseline compile (-O1) is doing okay:

--8<---------------cut here---------------start------------->8---
scheme@(gnu home services mpv)> ,use(system base compile)
scheme@(gnu home services mpv)> ,t (->bool (compile '(mpv-profile-configuration) #:to 'tree-il #:env (current-module)))
$20 = #t
;; 0.378741s real time, 0.377043s run time.  0.000000s spent in GC.
scheme@(gnu home services mpv)> ,t (->bool (compile '(mpv-profile-configuration) #:to 'bytecode #:env (current-module)))
$21 = #t
;; 11.946879s real time, 12.961704s run time.  1.777478s spent in GC.
scheme@(gnu home services mpv)> (define til (compile '(mpv-profile-configuration) #:to 'tree-il #:env (current-module)))
scheme@(gnu home services mpv)> ,t (->bool (compile til #:from 'tree-il #:to 'bytecode))
$22 = #t
;; 11.403420s real time, 12.317183s run time.  1.581972s spent in GC.
scheme@(gnu home services mpv)> ,t (->bool (compile til #:from 'tree-il #:to 'bytecode #:optimization-level 1))
$23 = #t
;; 0.225455s real time, 0.156137s run time.  0.000000s spent in GC.
--8<---------------cut here---------------end--------------->8---

Currently (guix build compile) applies these options to services:

        ((string-contains file "gnu/services/")
         ;; '-O2 -Ono-letrectify' compiles about ~20% faster than '-O2' for
         ;; large files like gnu/services/mail.scm.
         (override-option #:letrectify? #f
                          (optimizations-for-level 2)))

I think we should at least apply this patch:

diff --git a/guix/build/compile.scm b/guix/build/compile.scm
index 5b27b55d02..f90016b9ae 100644
--- a/guix/build/compile.scm
+++ b/guix/build/compile.scm
@@ -127,7 +127,8 @@ (define (optimization-options file)
          ;; Use '-O1' to have partial evaluation and primitive inlining so we
          ;; can honor the "macro writer's bill of rights".
          (optimizations-for-level 1))
-        ((string-contains file "gnu/services/")
+        ((or (string-contains file "gnu/services/")
+             (string-contains file "gnu/home/services/"))
          ;; '-O2 -Ono-letrectify' compiles about ~20% faster than '-O2' for
          ;; large files like gnu/services/mail.scm.
          (override-option #:letrectify? #f

Would that be enough for the home-mpv configuration records you wrote?

Thanks,
Ludo’.