guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: guix environment --profile with --ad-hoc


From: Ricardo Wurmus
Subject: Re: guix environment --profile with --ad-hoc
Date: Fri, 12 Mar 2021 12:23:45 +0100
User-agent: mu4e 1.4.14; emacs 27.1

Pierre Neidhardt <mail@ambrevar.xyz> writes:

> It seems to be some thing more than just Guix commands being slow.
> On my machine
>
>
> --8<---------------cut here---------------start------------->8---
> $ time guix environment --help >/dev/null
>
> real  0m0.345s
> --8<---------------cut here---------------end--------------->8---
>
> Which is 2s less than
>
> --8<---------------cut here---------------start------------->8---
> $ time guix environment --profile=/my/profile -- exit
>
> real  0m2.372s
> --8<---------------cut here---------------end--------------->8---
>
> So `guix environment --profile' seems to be pretty slow still.

https://elephly.net/downies/guix-env-perf.svg is a timechart recording
of “guix environment --profile=$HOME/.guix-profile -- exit”.  It shows
that 0.5s Guix is busy with itself, and then enters a back and forth
with the daemon.  The little thing at the end is where “exit” is invoked
(and fails).

strace reveals more.  For example, some time is lost searching libraries
and other files.  (At least the excessive library searches should
already have been mitigated by changes on the core-updates branch.)
This includes reading .go files, .scm files, reading TLS certs for
guile-gnutls, etc.

Then we finally connect to the daemon.  We read the profile manifest,
and then go on another search for Guile files, this time related to
package modules.  For every module it looks something like this:

--8<---------------cut here---------------start------------->8---
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/3.0/gnu/packages/commencement.scm",
 0x7ffdcfe812e0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/3.0/gnu/packages/commencement.scm",
 0x7ffdcfe812e0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/gnu/packages/commencement.scm",
 0x7ffdcfe812e0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/gnu/packages/commencement.scm",
 0x7ffdcfe812e0) = -1 ENOENT (No such file or directory)
6455  stat("/home/rekado/dev/gx/branches/master/gnu/packages/commencement.scm", 
{st_mode=S_IFREG|0644, st_size=159995, ...}) = 0
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/lib/guile/3.0/ccache/gnu/packages/commencement.go",
 0x7ffdcfe810f0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/lib/guile/3.0/site-ccache/gnu/packages/commencement.go",
 0x7ffdcfe810f0) = -1 ENOENT (No such file or directory)
6455  stat("/home/rekado/dev/gx/branches/master/gnu/packages/commencement.go", 
{st_mode=S_IFREG|0644, st_size=727379, ...}) = 0
6455  openat(AT_FDCWD, 
"/home/rekado/dev/gx/branches/master/gnu/packages/commencement.go", 
O_RDONLY|O_CLOEXEC) = 14
--8<---------------cut here---------------end--------------->8---

I’m guessing that we could avoid some of that searching (and thus
condense a whole lot of stat calls) by constraining things a little
ahead of time.  We know the location of Guile modules in advance, so
perhaps we can come up with a way to avoid having to go on
GUILE_LOAD_PATH and GUILE_LOAD_COMPILED_PATH for everything, e.g. by
recording GUIX_ROOT and using that.

Same for patches:

--8<---------------cut here---------------start------------->8---
…
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/3.0/binutils-boot-2.20.1a.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/3.0/binutils-boot-2.20.1a.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/binutils-boot-2.20.1a.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/binutils-boot-2.20.1a.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/home/rekado/dev/gx/branches/master/gnu/packages/patches/binutils-boot-2.20.1a.patch",
 {st_mode=S_IFREG|0644, st_size=6924, ...}) = 0
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/3.0/glibc-boot-2.16.0.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/3.0/glibc-boot-2.16.0.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/glibc-boot-2.16.0.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/glibc-boot-2.16.0.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/home/rekado/dev/gx/branches/master/gnu/packages/patches/glibc-boot-2.16.0.patch",
 {st_mode=S_IFREG|0644, st_size=13079, ...}) = 0
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/3.0/glibc-bootstrap-system-2.16.0.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/3.0/glibc-bootstrap-system-2.16.0.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/glibc-bootstrap-system-2.16.0.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/glibc-bootstrap-system-2.16.0.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/home/rekado/dev/gx/branches/master/gnu/packages/patches/glibc-bootstrap-system-2.16.0.patch",
 {st_mode=S_IFREG|0644, st_size=951, ...}) = 0
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/3.0/gcc-4.9-libsanitizer-fix.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/3.0/gcc-4.9-libsanitizer-fix.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/gcc-4.9-libsanitizer-fix.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/gcc-4.9-libsanitizer-fix.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/home/rekado/dev/gx/branches/master/gnu/packages/patches/gcc-4.9-libsanitizer-fix.patch",
 {st_mode=S_IFREG|0644, st_size=3291, ...}) = 0
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/3.0/gcc-4.9-libsanitizer-ustat.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/3.0/gcc-4.9-libsanitizer-ustat.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/gcc-4.9-libsanitizer-ustat.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/gcc-4.9-libsanitizer-ustat.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/home/rekado/dev/gx/branches/master/gnu/packages/patches/gcc-4.9-libsanitizer-ustat.patch",
 {st_mode=S_IFREG|0644, st_size=1473, ...}) = 0
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/3.0/gcc-4.9-libsanitizer-mode-size.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/3.0/gcc-4.9-libsanitizer-mode-size.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/site/gcc-4.9-libsanitizer-mode-size.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
6455  
stat("/gnu/store/m5iprcg6pb5ch86r9agmqwd8v6kp7999-guile-3.0.5/share/guile/gcc-4.9-libsanitizer-mode-size.patch",
 0x7ffdcfe80ef0) = -1 ENOENT (No such file or directory)
…
--8<---------------cut here---------------end--------------->8---

But this is still all rather benign.  The real slow-down is due to
talking to the daemon.  I’m not sure I understand all the strace output,
but it looks like we read file names from the daemon socket and then
write the contents of the builders and derivations for these files back
to the daemon socket.

It’s not clear to me if Guix computes these builders and derivations
from scratch and then sends them over the socket, or if it reads them
from files and sends them over.  But it does seem like perhaps we could
avoid some of the work, or at least some of the socket communication
when the daemon could read existing files directly.

In between we see again and again stat’ing of Scheme source files, that
are always first searched for in Guile’s output directory, of course in
vain.

It does this for all nodes in the graph, sources files, builders,
derivations, etc.  Lots of work.

So it’s not unsurprising that it takes longer than “guix environment
--help”, which doesn’t have to talk to the daemon at all.  The question
is just if we can avoid some of that work and if so how much of it.

-- 
Ricardo



reply via email to

[Prev in Thread] Current Thread [Next in Thread]