[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Loading a package applies automatically to future sessions?
From: |
Stefan Monnier |
Subject: |
Re: Loading a package applies automatically to future sessions? |
Date: |
Sun, 28 Jan 2018 17:11:07 -0500 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux) |
>> This said, if a package's activation gets in the way of the user, I'd
>> generally consider it to be a bug in that package (similar to the fact
>> that if (require <foo>) has undesirable effects it's usually a bug in
>> <foo>).
> Activation of packages is a significant performance hit.
> It's therefore not a good idea to be activating superfluous packages.
> JW has told me that one of the reasons his Emacs configuration does
> not use package.el is that activating packages was too slow.
The performance impact is indeed something that probably deserves a bit
more work. But we need to clarify what are the expected use cases and
sources of problems. E.g.:
- In the case of JW, why does he have so many packages installed to slow
down his startup, yet he doesn't want them activated? Are these
packages that he does use, but just rarely? Or does he just have lots of
packages installed that he doesn't use (e.g. that's my case: I always
have all GNU ELPA packages installed, even though I use very few of
them)? If so, why does he have so many packages installed even tho he
doesn't use them?
- In my case I have around 200 packages installed and I measured the
startup cost of package-initialize to be 0.9s (with a warm cache).
That's plenty fast for my use case (where I rarely start a new Emacs
session), but I understand it may not be for people who like to use
Emacs for quick one-off editing sessions. Still, what kind of
slowdown is JW talking about: is it also in the order of 1s? more?
If the slowdown is significant, could it be due to packages that do
"too much work" in the <pkg>-autoloads.el or is it really just the
sheer number of <pkg>-autoloads.el and <pkg>-pkg.el to process?
The issue came up recently on stackexchange and I whipped up
a quick&dirty patch to experiment (see below) which shows that my 0.9s
can be brought down to 0.3s by pre-computing a "big autoloads file",
which can then be brought down to 0.2s by loading it with
load-source-file-function bound to nil and can be reduced further to
0.1s by byte-compiling it.
Another thing we could do is add support for activating a package
without calling package-initialize beforehand (since just calling
(package-initialize t) can already take a non-negligible amount of time,
reading all the <pkg>-pkg.el files). This way, a user could simply skip
package-initialize completely and just "manually" activate those few
packages he wants to activate. It should be fairly easy to implement.
Stefan
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 71d1c41ec3..63ec6f40f7 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -676,6 +676,8 @@ package--activate-autoloads-and-load-path
(defvar Info-directory-list)
(declare-function info-initialize "info" ())
+(defvar package--fastpath-pkgs t)
+
(defun package--load-files-for-activation (pkg-desc reload)
"Load files for activating a package given by PKG-DESC.
Load the autoloads file, and ensure `load-path' is setup. If
@@ -718,16 +720,19 @@ package-activate-1
(message "Unable to activate package `%s'.\nRequired package
`%s-%s' is unavailable"
name (car req) (package-version-join (cadr req)))
(throw 'exit nil))))
- (package--load-files-for-activation pkg-desc reload)
- ;; Add info node.
- (when (file-exists-p (expand-file-name "dir" pkg-dir))
- ;; FIXME: not the friendliest, but simple.
- (require 'info)
- (info-initialize)
- (push pkg-dir Info-directory-list))
- (push name package-activated-list)
- ;; Don't return nil.
- t)))
+ (if (listp package--fastpath-pkgs)
+ ;; We're only collecting the set of packages to activate!
+ (push pkg-desc package--fastpath-pkgs)
+ (package--load-files-for-activation pkg-desc reload)
+ ;; Add info node.
+ (when (file-exists-p (expand-file-name "dir" pkg-dir))
+ ;; FIXME: not the friendliest, but simple.
+ (require 'info)
+ (info-initialize)
+ (push pkg-dir Info-directory-list))
+ (push name package-activated-list)
+ ;; Don't return nil.
+ t))))
(declare-function find-library-name "find-func" (library))
@@ -3468,6 +3473,49 @@ package-list-packages-no-fetch
(interactive)
(list-packages t))
+;;;; Fast-path for activation!
+
+(defcustom package-fastpath-file (locate-user-emacs-file "package-fastpath.el")
+ "Location of the file used to speed up activation of packages at startup."
+ :type 'file)
+
+(defun package-fastpath-refresh ()
+ "(Re)Generate the `package-fastpath-file'."
+ (interactive)
+ (package-initialize 'no-activate)
+ (let ((package--fastpath-pkgs ())
+ ;; Pretend we haven't activated anything yet!
+ (package-activated-list ()))
+ (dolist (elt package-alist)
+ (condition-case err
+ (package-activate (car elt))
+ ;; Don't let failure of activation of a package arbitrarily stop
+ ;; activation of further packages.
+ (error (message "%s" (error-message-string err)))))
+ (with-temp-file package-fastpath-file
+ (insert ";;; FastPath file to speed up package activation at startup
-*- lexical-binding:t -*-\n")
+ (insert ";; ¡¡ This file is autogenerated, DO NOT EDIT !!\n\n")
+ (dolist (pkg package--fastpath-pkgs)
+ (let* ((file (locate-library (package--autoloads-file-name pkg)))
+ (pfile (prin1-to-string file)))
+ (insert "(let ((load-file-name " pfile "))\n")
+ (insert-file-contents file)
+ (while (search-forward "#$" nil 'move)
+ (replace-match pfile t t))
+ (unless (bolp) (insert "\n"))
+ (insert ")\n")))
+ (pp `(setq package-activated-list
+ (append ',(mapcar #'package-desc-name package--fastpath-pkgs)
+ package-activated-list))
+ (current-buffer))
+ (insert "
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: nil
+;; no-update-autoloads: t
+;; End:
+"))))
+
(provide 'package)
;;; package.el ends here
- Re: Loading a package applies automatically to future sessions?, (continued)
- Re: Loading a package applies automatically to future sessions?, Radon Rosborough, 2018/01/29
- Re: Loading a package applies automatically to future sessions?, Radon Rosborough, 2018/01/26
- Re: Loading a package applies automatically to future sessions?, Eli Zaretskii, 2018/01/26
- Re: Loading a package applies automatically to future sessions?, Radon Rosborough, 2018/01/28
- Re: Loading a package applies automatically to future sessions?, Richard Stallman, 2018/01/28
- Re: Loading a package applies automatically to future sessions?, Richard Stallman, 2018/01/27
- Re: Loading a package applies automatically to future sessions?, Radon Rosborough, 2018/01/28
- Re: Loading a package applies automatically to future sessions?, Charles A. Roelli, 2018/01/28
- Re: Loading a package applies automatically to future sessions?, Stefan Monnier, 2018/01/28
- Re: Loading a package applies automatically to future sessions?, Radon Rosborough, 2018/01/28
- Re: Loading a package applies automatically to future sessions?,
Stefan Monnier <=
- Re: Loading a package applies automatically to future sessions?, T.V Raman, 2018/01/28
- Re: Loading a package applies automatically to future sessions?, Radon Rosborough, 2018/01/29
- Re: Loading a package applies automatically to future sessions?, John Wiegley, 2018/01/29
- Re: Loading a package applies automatically to future sessions?, Stefan Monnier, 2018/01/29
- Re: Loading a package applies automatically to future sessions?, John Wiegley, 2018/01/29
- Re: Loading a package applies automatically to future sessions?, Stefan Monnier, 2018/01/29
- Re: Loading a package applies automatically to future sessions?, John Wiegley, 2018/01/29
- Re: Loading a package applies automatically to future sessions?, Stefan Monnier, 2018/01/29
- Re: Loading a package applies automatically to future sessions?, John Wiegley, 2018/01/29
- Re: Loading a package applies automatically to future sessions?, Stefan Monnier, 2018/01/29