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

From: Tomas Volf <[email-masked]>
Date: Fri, 27 Dec 2024 23:50:06 +0100

Hello,

thank you for finding the time to look into this issue.  Replies below.

Ludovic Courtès <[email-masked]> writes:

> 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:
>
> 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.
>
>
> If we look more closely, it’s the optimizing compiler that takes time;
> the baseline compile (-O1) is doing okay:
>
> 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.
>
> 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?

I admit I did not test the patch attached, but my understanding is that
even if the speed up was sufficient, it would take effect only for
compilation via the make command.  Assuming that is correct, it would
not change much.  I am (luckily) former C++ developer, so I am used to
compilations taking ~forever.  So, yes, while the compilation of mpv.scm
(via `make') took roughly 40s on my machine, it was annoying, but not
worthy of a bug report.

The actual problem for me was the slowness in REPL.  Would that be
addressed by the patch above?  If not, do we have any way to do that?

)tomas

-- 
There are only two hard things in Computer Science:
cache invalidation, naming things and off-by-one errors.