GNU bug report logs - #41646
Startup in Windows is very slow when load-path contains many entries.

Previous Next

Package: emacs;

Reported by: Nicolas Bértolo <nicolasbertolo <at> gmail.com>

Date: Mon, 1 Jun 2020 14:27:02 UTC

Severity: minor

Tags: fixed, patch

Fixed in version 28.1

Done: Lars Ingebrigtsen <larsi <at> gnus.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 41646 in the body.
You can then email your comments to 41646 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Mon, 01 Jun 2020 14:27:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Nicolas Bértolo <nicolasbertolo <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Mon, 01 Jun 2020 14:27:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: Startup in Windows is very slow when load-path contains many entries.
Date: Mon, 1 Jun 2020 11:26:35 -0300
I have an issue regarding startup times in Windows. My configuration is
Spacemacs with many layers enabled. My load-path contains 380 entries.

I have profiled Emacs in Windows and found that it spends most of the startup
time calling wopen(). This is because when calling (load "foo") it checks all
directories in load-path for ("foo.el" "foo.elc" "foo.el.gz" "foo.elc.gz"
"foo.dll"). It gets worse when load-prefer-newer is t.

In my case `load-path` contains 380 entries, so every call to load will perform
380 * 5 = 1900 calls to wopen. This is very slow in Windows because its
filesystem is not optimized for so many accesses to small files.

I thought that a caching mechanism would help.

This "cache" would consist of a mapping of files that would get probed when
(load "foo") runs. It would be implemented as a hash table. The contents of this
hash table could be loaded from load-cache.el files in each package directory.

The directory foo-pkg could have a file load-cache.el with:

foo -> ("foo-pkg/foo.el"
        "foo-pkg/foo.elc")
[...]

The directory bar-pkg could have a file load-cache.el with:

bar -> ("bar-pkg/bar.el"
        "bar-pkg/bar.elc")
[...]

When a package is activated we could update the in-memory hash table by loading
its load-cache.el file. Then, when (require 'foo) runs, the loading code could
look at the hash table and only fopen() the files associated with the feature we
are loading. This would reduce the number of calls to fopen() from thousands to
~2 in the worst case.

Or we could have a big load-cache.el in `package-user-dir'. I prefer many small
files because maintaining the big file when many Emacs instances could be
installing or removing packages is synchronization nightmare.

Of course, this feature would be disabled by default.

What do you think?

Nicolas




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Mon, 01 Jun 2020 16:07:01 GMT) Full text and rfc822 format available.

Message #8 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
Cc: 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path contains
 many entries.
Date: Mon, 01 Jun 2020 19:05:58 +0300
> From: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
> Date: Mon, 1 Jun 2020 11:26:35 -0300
> 
> I have an issue regarding startup times in Windows. My configuration is
> Spacemacs with many layers enabled. My load-path contains 380 entries.
> 
> I have profiled Emacs in Windows and found that it spends most of the startup
> time calling wopen(). This is because when calling (load "foo") it checks all
> directories in load-path for ("foo.el" "foo.elc" "foo.el.gz" "foo.elc.gz"
> "foo.dll"). It gets worse when load-prefer-newer is t.
> 
> In my case `load-path` contains 380 entries, so every call to load will perform
> 380 * 5 = 1900 calls to wopen. This is very slow in Windows because its
> filesystem is not optimized for so many accesses to small files.

So this is not specific to Windows, it's just that Windows has slower
file access.  IOW, if load-path becomes significantly larger, the slow
startup will show on Posix systems as well, right?

Next question: are the 'wopen' calls coming from 'openp'? if so,
perhaps we could first try a cheaper call, like 'chmod' (or its Win32
API equivalent), and save the 'wopen' call if 'chmod' fails?  Did you
try that?

> I thought that a caching mechanism would help.

My main concern with a cache is how to make sure it reflects what's on
the disk, when files are added or removed.

Thanks.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Mon, 01 Jun 2020 16:47:01 GMT) Full text and rfc822 format available.

Message #11 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path
 contains many entries.
Date: Mon, 1 Jun 2020 13:46:01 -0300
> So this is not specific to Windows, it's just that Windows has slower
> file access.  IOW, if load-path becomes significantly larger, the slow
> startup will show on Posix systems as well, right?

Exactly, but not nearly as bad. I profiled the same Spacemacs configuration in
Ubuntu 20.04 and startup takes 10 seconds, with 5 seconds spent inside openp().

Compare this to 40 seconds in total and 32 seconds inside openp() in Windows.

> Next question: are the 'wopen' calls coming from 'openp'? if so,
> perhaps we could first try a cheaper call, like 'chmod' (or its Win32
> API equivalent), and save the 'wopen' call if 'chmod' fails?  Did you
> try that?

They come from openp(), yes. I haven't tried it. I think the issue is related to
the IO architecture in Windows, so I don't expect major speedups, but it could
certainly help.

> My main concern with a cache is how to make sure it reflects what's on
> the disk, when files are added or removed.

That is my main concern as well. A good option would be to rely on package.el to
generate the load-cache.el file for a package when it generates autoloads. If we
can't find any of the files mentioned in the cache then we fallback to the
current load-path code. That is a simple solution that would take care of
addition and removal of files, I think.

Nico.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Mon, 01 Jun 2020 17:18:01 GMT) Full text and rfc822 format available.

Message #14 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
Cc: 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path
 contains many entries.
Date: Mon, 01 Jun 2020 20:17:19 +0300
> From: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
> Date: Mon, 1 Jun 2020 13:46:01 -0300
> Cc: 41646 <at> debbugs.gnu.org
> 
> > So this is not specific to Windows, it's just that Windows has slower
> > file access.  IOW, if load-path becomes significantly larger, the slow
> > startup will show on Posix systems as well, right?
> 
> Exactly, but not nearly as bad. I profiled the same Spacemacs configuration in
> Ubuntu 20.04 and startup takes 10 seconds, with 5 seconds spent inside openp().
> 
> Compare this to 40 seconds in total and 32 seconds inside openp() in Windows.

You may be surprised how many users of GNU/Linux consider 5 sec during
startup an unacceptable slowdown.

> > Next question: are the 'wopen' calls coming from 'openp'? if so,
> > perhaps we could first try a cheaper call, like 'chmod' (or its Win32
> > API equivalent), and save the 'wopen' call if 'chmod' fails?  Did you
> > try that?
> 
> They come from openp(), yes. I haven't tried it. I think the issue is related to
> the IO architecture in Windows, so I don't expect major speedups, but it could
> certainly help.

'chmod' doesn't access the file, it only accesses the directory.  So
it could be much faster.

> > My main concern with a cache is how to make sure it reflects what's on
> > the disk, when files are added or removed.
> 
> That is my main concern as well. A good option would be to rely on package.el to
> generate the load-cache.el file for a package when it generates autoloads. If we
> can't find any of the files mentioned in the cache then we fallback to the
> current load-path code. That is a simple solution that would take care of
> addition and removal of files, I think.

Is this supposed to work only when packages are installed by
package.el?  What about manual installation?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Mon, 01 Jun 2020 19:52:02 GMT) Full text and rfc822 format available.

Message #17 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path
 contains many entries.
Date: Mon, 1 Jun 2020 16:51:11 -0300
> You may be surprised how many users of GNU/Linux consider 5 sec during
> startup an unacceptable slowdown.

Me too. But I had given up on it until I read how it was implemented.

> 'chmod' doesn't access the file, it only accesses the directory.  So
> it could be much faster.

As far as I can see there is no way to issue a call to 'chmod' that does not
try to change the permissions of the file passed. I will try to do it
with access().

> Is this supposed to work only when packages are installed by
> package.el?  What about manual installation?

Everything should work OK as long as you provide a load-cache.el file in the
directory you add to load-path. We could provide a function to generate it
automatically.

Thanks, Nico




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Tue, 02 Jun 2020 02:19:02 GMT) Full text and rfc822 format available.

Message #20 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
Cc: 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path
 contains many entries.
Date: Tue, 02 Jun 2020 05:17:40 +0300
> From: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
> Date: Mon, 1 Jun 2020 16:51:11 -0300
> Cc: 41646 <at> debbugs.gnu.org
> 
> > 'chmod' doesn't access the file, it only accesses the directory.  So
> > it could be much faster.
> 
> As far as I can see there is no way to issue a call to 'chmod' that does not
> try to change the permissions of the file passed. I will try to do it
> with access().

Sorry, I meant 'access', of course.  More accurately,
GetFileAttributes.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Wed, 03 Jun 2020 01:09:01 GMT) Full text and rfc822 format available.

Message #23 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path
 contains many entries.
Date: Tue, 2 Jun 2020 22:07:45 -0300
[Message part 1 (text/plain, inline)]
> Sorry, I meant 'access', of course.  More accurately,
> GetFileAttributes.

That was a very good idea. The attached patch reduces time spent
in openp() during startup by 5 seconds, or 15%.

Thanks, Nico.
[0001-In-Windows-check-if-file-exists-before-opening-it.patch (application/octet-stream, attachment)]

Added tag(s) patch. Request was from Stefan Kangas <stefan <at> marxist.se> to control <at> debbugs.gnu.org. (Thu, 13 Aug 2020 01:13:03 GMT) Full text and rfc822 format available.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Fri, 14 Aug 2020 17:23:01 GMT) Full text and rfc822 format available.

Message #28 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Nicolas Bértolo <nicolasbertolo <at> gmail.com>
Cc: Eli Zaretskii <eliz <at> gnu.org>, 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path
 contains many entries.
Date: Fri, 14 Aug 2020 19:22:26 +0200
Nicolas Bértolo <nicolasbertolo <at> gmail.com> writes:

>> Sorry, I meant 'access', of course.  More accurately,
>> GetFileAttributes.
>
> That was a very good idea. The attached patch reduces time spent
> in openp() during startup by 5 seconds, or 15%.

That's a huge speed-up indeed.

[...]

> -		fd = emacs_open (pfn, O_RDONLY, 0);
> +                /*  In some systems (like Windows) finding out if a
> +                    file exists is cheaper to do than actually opening
> +                    it.  Only open the file when we are sure that it
> +                    exists.  */
> +#ifdef WINDOWSNT
> +                if (faccessat (AT_FDCWD, pfn, R_OK, AT_EACCESS))
> +                  fd = -1;
> +                else
> +#endif
> +                  fd = emacs_open (pfn, O_RDONLY, 0);
> +

This is a Windows-specific patch, so I have no opinion on it.  Eli?
Does this make sense to you?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Fri, 14 Aug 2020 19:08:02 GMT) Full text and rfc822 format available.

Message #31 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: nicolasbertolo <at> gmail.com, 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path
 contains many entries.
Date: Fri, 14 Aug 2020 22:07:15 +0300
> From: Lars Ingebrigtsen <larsi <at> gnus.org>
> Cc: Eli Zaretskii <eliz <at> gnu.org>,  41646 <at> debbugs.gnu.org
> Date: Fri, 14 Aug 2020 19:22:26 +0200
> 
> > That was a very good idea. The attached patch reduces time spent
> > in openp() during startup by 5 seconds, or 15%.
> 
> That's a huge speed-up indeed.
> 
> [...]
> 
> > -		fd = emacs_open (pfn, O_RDONLY, 0);
> > +                /*  In some systems (like Windows) finding out if a
> > +                    file exists is cheaper to do than actually opening
> > +                    it.  Only open the file when we are sure that it
> > +                    exists.  */
> > +#ifdef WINDOWSNT
> > +                if (faccessat (AT_FDCWD, pfn, R_OK, AT_EACCESS))
> > +                  fd = -1;
> > +                else
> > +#endif
> > +                  fd = emacs_open (pfn, O_RDONLY, 0);
> > +
> 
> This is a Windows-specific patch, so I have no opinion on it.  Eli?
> Does this make sense to you?

Not sure.  15% sounds too little for having OS-specific code in that
place.  I hoped it will be much more.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Thu, 13 May 2021 09:18:02 GMT) Full text and rfc822 format available.

Message #34 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: nicolasbertolo <at> gmail.com, 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path
 contains many entries.
Date: Thu, 13 May 2021 11:17:07 +0200
Eli Zaretskii <eliz <at> gnu.org> writes:

>> This is a Windows-specific patch, so I have no opinion on it.  Eli?
>> Does this make sense to you?
>
> Not sure.  15% sounds too little for having OS-specific code in that
> place.  I hoped it will be much more.

So would your preference be to not apply the patch?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Thu, 13 May 2021 10:21:01 GMT) Full text and rfc822 format available.

Message #37 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Lars Ingebrigtsen <larsi <at> gnus.org>
Cc: nicolasbertolo <at> gmail.com, 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path
 contains many entries.
Date: Thu, 13 May 2021 13:20:58 +0300
> From: Lars Ingebrigtsen <larsi <at> gnus.org>
> Cc: nicolasbertolo <at> gmail.com,  41646 <at> debbugs.gnu.org
> Date: Thu, 13 May 2021 11:17:07 +0200
> 
> Eli Zaretskii <eliz <at> gnu.org> writes:
> 
> >> This is a Windows-specific patch, so I have no opinion on it.  Eli?
> >> Does this make sense to you?
> >
> > Not sure.  15% sounds too little for having OS-specific code in that
> > place.  I hoped it will be much more.
> 
> So would your preference be to not apply the patch?

No, I guess it's okay after all, so let's install it.

TIA




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#41646; Package emacs. (Thu, 13 May 2021 11:32:02 GMT) Full text and rfc822 format available.

Message #40 received at 41646 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: nicolasbertolo <at> gmail.com, 41646 <at> debbugs.gnu.org
Subject: Re: bug#41646: Startup in Windows is very slow when load-path
 contains many entries.
Date: Thu, 13 May 2021 13:31:37 +0200
Eli Zaretskii <eliz <at> gnu.org> writes:

> No, I guess it's okay after all, so let's install it.

OK; I tested the patch on a Windows VM, and Emacs seemed to start
normally, as far as I could tell (but I didn't test it further than
that).

Pushed to Emacs 28 now.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Added tag(s) fixed. Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Thu, 13 May 2021 11:32:02 GMT) Full text and rfc822 format available.

bug marked as fixed in version 28.1, send any further explanations to 41646 <at> debbugs.gnu.org and Nicolas Bértolo <nicolasbertolo <at> gmail.com> Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Thu, 13 May 2021 11:32:03 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Fri, 11 Jun 2021 11:24:05 GMT) Full text and rfc822 format available.

This bug report was last modified 2 years and 318 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.