Subject: [bug#49421] [PATCH] profiles: Optimise 'fonts-dir-file'.

From: Ludovic Courtès <[email-masked]>
Date: Wed, 07 Jul 2021 18:52:54 +0200

Hi,

Maxime Devos <[email-masked]> skribis:

> These two patches should speed up profile generation
> by optimising the 'fonts-dir-file' hook.  The first patch
> is the most important; from the commit message:
>
> ‘Only let the build G-exp refer to inputs that might actually
> have fonts.  That way, if the list of fonts in the manifest
> didn't change and the new manifest is built, the font files
> will not be rebuilt.’
>
> The second patch doesn't bring much.
>
> To test, you can test whether things like ...
>
> $ ./pre-inst-env guix environment --ad-hoc --pure lagrange -- lagrange
>
> still work (lagrange is a graphical application using fonts).
> Not sure what a good ‘benchmark’ would be.
>
> Unfortunately, this does not help with the "guix package -i" case,
> as in that case, the code doesn't have access to all the package objects,
> and will have to satisfy itself with the store paths, in which case the
> profile code pessimistically assumes the store item has fonts ...
>
> I suppose this restriction could be lifted if/when the gs-fonts package
> is renamed to font-ghostscript or something like that ...

Do you know what’s taking time in the ‘fonts-dir-file’ hook?
(On my x86_64 laptop with SSD, it runs in 4.4s on a cold cache for a
profile containing 14 font packages, and in 1.2s on a warm cache.)

IIUC, the hook completes almost instantaneously when creating a profile
without fonts because (null? fonts-dirs) is true.

In other cases, one option to speed things up (and possibly remove the
hook’s dependency on mkfontdir) would be to create ‘fonts.dir’ and
‘fonts.scale’ in a build phase of each font package, *provided* there’s
a cheap way to assemble several such files, such as mere concatenation.
That way, the profile hook would only need to assemble these files as
opposed to traversing all the font files.

Given that ‘fonts.dir’ and ‘fonts.scale’ are mere text files with one
line per font, this approach looks doable.

WDYT?

> From 4fe1e30e33c01be9fd17cf240732b3351c7b0fa4 Mon Sep 17 00:00:00 2001
> From: Maxime Devos <[email-masked]>
> Date: Mon, 5 Jul 2021 18:55:31 +0200
> Subject: [PATCH 1/2] profiles: Optimise 'fonts-dir-file'.
>
> Only let the build G-exp refer to inputs that might actually
> have fonts.  That way, if the list of fonts in the manifest
> didn't change and the new manifest is built, the font files
> will not be rebuilt.
>
> * guix/profiles.scm
>   (fonts-dir-file)[has-fonts?]: New predicate.
>   (fonts-dir-file)[relevant-inputs]: New variable.
>   (fonts-dir-file)[build]: Use 'relevant-inputs' instead of
>   'manifest-inputs'.
> * doc/contributing.texi (Fonts): Note the 'fonts-' naming
>   convention is technically important now.
> * gnu/packages/ghostscript.scm (gs-fonts): Work-around the
>   package name contravening the convention.

To me this approach should be a last resort because it relies on
conventions and manual annotations, and it’s easy to forget these and
get incorrect results (we could end up having to deal with reports like
“I installed font X, why doesn’t in show up in the font list?”).

> +            ;; In the upstream 'guix' channel, font packages should
> +            ;; be named font-SOMETHING.  But if another channel
> +            ;; names its fonts differently but uses font-build-system,
> +            ;; accepting that seems friendly.
> +            (eq? 'font (build-system-name (package-build-system thing)))

In general ‘build-system-name’ shouldn’t be used; the name is meant to
be a debugging aid.

Thanks,
Ludo’.