Would it not be possible to modify Emacs package system to store all Emacs Lisp files installed from Elpa-compliant packages inside the same directory?
That would dramatically reduce the number of entries inside Emacs load-path and would speed up Emacs startup time, would it not?
On my system I have:
- 208 directories in my
~/.emacs.d/elpa
directory, - 182 directories out of these 208 have only files in them, no sub-directories.
I wrote the following Makefile rules in my build system:
.PHONY: timeit
timeit:
@printf "***** Running Emacs startup time measurement tests\n"
@printf "** Report Configuration settings.\n"
$(EMACS) --batch -L . -l $(EMACS_INIT) -l pel-package.el -f pel-package-info
@printf "\n"
@printf "** Time mesaurement:\n"
time -p $(EMACS) -nw -Q -e kill-emacs
time -p $(EMACS) -nw -q -e kill-emacs
time -p $(EMACS) -nw -e kill-emacs
My pel-package-info gathers information about the package I use and prints a report on the number used, the load-path, etc...
When I run it a couple of times (with Emacs 26.3) I get something like this:
> make timeit
***** Running Emacs startup time measurement tests
** Report Configuration settings.
emacs --batch -L . -l "~/.emacs.d/init.el" -l pel-package.el -f pel-package-info
Loading /Users/roup/.emacs.d/emacs-customization.el (source)...
Loading pel_keys...
Loading /Users/roup/.emacs.d/recentf...
Cleaning up the recentf list...
Cleaning up the recentf list...done (0 removed)
PEL loaded, PEL keys binding in effect.
size of load-path : 241 directories
Number of PEL user-options : 250 (198 are active)
PEL activated elpa packages: 167 ( 45 dependants, 5 imposed by restrictions)
PEL Activated utils files : 25 ( 0 dependants, 0 imposed by restrictions)
** Time mesaurement:
time -p emacs -nw -Q -e kill-emacs
real 0.13
user 0.02
sys 0.01
time -p emacs -nw -q -e kill-emacs
real 0.13
user 0.02
sys 0.01
time -p emacs -nw -e kill-emacs
real 1.66
user 0.98
sys 0.55
>
As a small (yet incomplete) experiment:
- I created another directory (
~/tmp/roup
).- Inside that directory I created symlinks for all .el and .elc files of elpa sub-directories that do not have subdirectories (the 182 directories described above).
- I placed that
~/tmp/roup
directory at the front of Emacsload-path
. - I left everything else unchanged.
Then I ran the same test a couple of times and I got something like this:
> make timeit
***** Running Emasc startup time measurement tests
** Report Configuration settings.
emacs --batch -L . -l "~/.emacs.d/init.el" -l pel-package.el -f pel-package-info
Loading /Users/roup/.emacs.d/emacs-customization.el (source)...
Loading pel_keys...
Loading /Users/roup/.emacs.d/recentf...
Cleaning up the recentf list...
Cleaning up the recentf list...done (0 removed)
PEL loaded, PEL keys binding in effect.
size of load-path : 242 directories
Number of PEL user-options : 250 (198 are active)
PEL activated elpa packages: 167 ( 45 dependants, 5 imposed by restrictions)
PEL Activated utils files : 25 ( 0 dependants, 0 imposed by restrictions)
** Time mesaurement:
time -p emacs -nw -Q -e kill-emacs
real 0.13
user 0.02
sys 0.01
time -p emacs -nw -q -e kill-emacs
real 0.13
user 0.02
sys 0.01
time -p emacs -nw -e kill-emacs
real 1.50
user 0.92
sys 0.46
>
The time measurement is not very accurate as it is affected by other system operations, but I ran them several times and got similar results.
So just by providing a directory with symlinks to several of the files that are used during startup I was able to shave about 0.16 second from startup.
That's a 10% reduction of the startup time.
With Emacs 27.2, with or without package-quickstart, I get similar results (yet Emacs 27.2 is a little faster.)
By removing the 182 directories from the ~/.emacs.d/elpa
directory and place the .el and .elc files into ~/.emacs.d/elpa-files
then put this in front of the load-path (replacing the directory with symlinks) I reduced the time back to 0.77 secs:
** Time measurement:
time -p emacs -nw -Q -e kill-emacs
real 0.13
user 0.02
sys 0.01
time -p emacs -nw -q -e kill-emacs
real 0.14
user 0.03
sys 0.01
time -p emacs -nw -e kill-emacs
real 0.77
user 0.58
sys 0.08
>
The ~/.emacs.d/elpa-files
holds 1612 files. This is a large number of files but the end result is that it reduces the startup time quite a bit.
Question: Would it not be possible to modify the design of Emacs package managing logic to store all the .el and .elc inside a same directory?
We would have to create some other files to remember the package version number that have been installed and their files. But that processing would only occur during a package install or removal, it would not affect Emacs startup time.
Is there something in package.el that makes this strategy difficult or impossible?
- Currently the package inter-dependency checking breaks when package directories identifying the dependents and package detection fail.s But I assume this could be overcome if the installed packages were identified in some form of local db/list.