TL; DR J'ai une telle quantité de paquets que ça me fait mal au démarrage. Si vous ne pensez pas que cela pourrait être le cas, lisez la suite.
Mon temps de démarrage Emacs est assez petit. Je ne l'utilise pas use-package
, je mets juste des tonnes de hooks et autoload
s pour que presque tout le code soit différé. En réalité, le tout est chargé en généralement moins d'une demi-seconde, même si cela semble être un gâchis fou.
Cependant, au fil du temps, j'ai remarqué que mon temps de démarrage était extrêmement lent, inexplicablement. Ceci est finalement arrivé au point où le temps de démarrage est ≥ 1 seconde. J'en ai finalement eu assez et j'ai creusé à la racine du problème. J'ai finalement commenté tout mon ~/.emacs
fichier et constaté que le temps de démarrage était toujours ≥ 1 seconde. En fait, il ne s'était rasé qu'environ 0.2
quelques secondes, parfois même moins. Ensuite, j'ai essayé emacs -q
et constaté que le temps de démarrage était de ~ 0.1
secondes.
En examinant cette section du manuel Elisp, j'ai découvert pourquoi emacs -q
le temps de démarrage était tellement réduit. Apparemment emacs -q
, Emacs empêche trois choses au démarrage:
- chargement de votre fichier init
- chargement de votre
default.el
fichier - appel
package-initialize
Nous avons déjà exclu mon fichier init, car commenter mon tout ~/.emacs
ne fait presque rien. Je n'utilise pas de default.el
fichier, ce qui est également exclu. Ce qui laisse package-initialize
le coupable du succès de la performance.
Pourquoi prendrait package-initialize
autant de temps de démarrage? C'était la première question que je me posais. Ne suis-je pas en train de tout charger automatiquement? Hé bien oui. Mais c'est précisément le problème.
J'ai trouvé ce post qui explique que "l'activation" des packages consiste à lire des fichiers de chargement automatique et à définir des chemins de chargement. Cela entraîne évidemment une pénalité d'E / S lorsque vous avez plusieurs packages car vous avez de nombreux fichiers à chargement automatique à lire et de nombreux chemins à définir. Malheureusement, sans cela, la tâche de gérer les chargements automatiques incombe à l'utilisateur. En d'autres termes, sans laisser package.el
explorer le système de fichiers pour les fichiers et les chemins de chargement automatique, je devrais gérer moi-même ce qui pourrait être un processus fastidieux et sujet aux erreurs.
Je préférerais ne pas emprunter cette voie. J'ai actuellement 116 packages, dont 107 d'ELPA et 25 de dépendances. Je suis sûr que ce nombre énorme est ce qui dégrade si gravement mes performances. Mais je suis dans un dilemme car je ne veux supprimer aucun de mes packages.
Existe-t-il un remède dans une telle situation pour récupérer mon temps de démarrage de la foudre?
Mise à jour:
Nous avons commencé un nouveau fil sur la emacs-devel
liste de diffusion sur certains correctifs par Stefan Monnier (une description de ces correctifs est ici ) pour résoudre ce problème. Tout le monde est invité à tester ses correctifs et à donner son avis.
Une autre mise à jour:
Il semble que Stefan Monnier ne soit plus intéressé par ce problème ou qu'il ne reçoive pas mes messages. Je suis enclin à croire le premier, ce qui est bien, mais j'apprécierais une sorte de réponse de sa part si tel est le cas. Quoi qu'il en soit, le code qu'il a produit jusqu'à présent pour ce numéro fonctionne assez bien. Les patchs les plus récents sont disponibles ici (pour Emacs 25.3) et ici (pour Emacs master branch).J'ai vu de bonnes améliorations sur mon temps de démarrage grâce à ses correctifs et je suis à un point où je suis à l'aise avec mon temps de démarrage dans la mesure où il est aussi optimisé que possible sans couper les fonctionnalités de ma personnalisation. J'espérais que ces correctifs arriveraient dans la ligne principale d'Emacs à un moment donné, mais je suppose que moi (ou quelqu'un d'autre) devrais reprendre le flambeau maintenant, au lieu de Stefan. Nous avions un peu de spar sur la liste de diffusion sur l'attribution des droits d'auteur et les licences. J'étais initialement mal à l'aise de le faire, mais en raison de certains commentaires de Richard Stallman et d'autres, la cession des droits d'auteur peut ne pas être aussi restrictive que je le pensais à l'origine. De plus, il peut être possible pour moi de placer mes œuvres dans le domaine public comme alternative à la cession du droit d'auteur.
En tout cas, merci Stefan pour les patchs à ce jour! J'espère que vous continuerez à développer ces changements, mais sinon, ça va et je pourrai continuer à les développer à un moment donné. Je remercie également toutes les autres personnes qui ont offert leur avis et leur contribution à la résolution de ce problème.
Encore une autre mise à jour:
Wow, on dirait que cette fonctionnalité a finalement atterri et sera dans Emacs 27. Merci à Stefan Monnier!
use-package
est la voie à suivre pour cela.Réponses:
L'un des choix de conception de package.el était d'essayer de simplifier les choses. Cela consiste en partie à
package-initialize
rechercher tous les packages installés, puis à essayer de déterminer lesquels doivent être activés (en fonction de l'épinglage et de la récence des versions dans le cas où plusieurs versions du même package sont disponibles), puis à charger chacun active le<pkg>-autoloads.el
fichier du package .Donc, pour N packages installés, cela signifie essentiellement lire N
<pkg>-pkg.el
fichiers de description de package et N<pkg>-autoloads.el
fichiers. Pour les grands N, cela peut devenir un problème grave. Un autre problème de performance potentiel est qu'il ajoutera N élémentsload-path
, donc à chaque fois que vousload
Emacs recherchera dans N répertoires, chacunload
sera donc ralenti.Nous pouvons essayer d'accélérer cela de différentes manières:
Fournir un moyen de précalculer un
~/.emacs.d/elpa/package-initialize.el(c)
fichier qui résulterait de la concaténation de tous les droits<pkg>-autoloads.el
dans le bon ordre. Ensuite,package-initialize
pourrait simplement charger ce fichier lorsqu'il est présent et ignorer tout le reste. Vous auriez alors besoin d'un moyen d'actualiser / vider lepackage-initialize.el(c)
fichier lorsque des packages sont ajoutés / mis à jour / supprimés ou lorsque vous modifiez votrepackage-pinned-packages
ou votrepackage-load-list
. Je pense que cela peut être fait avec assez peu de modifications du système (la seule chose qui aurait vraiment besoin d'être modifiée, je pensepackage-initialize
, c'est qu'on puisse lui dire de "n'activer que" sans charger les métadonnées sur les packages disponibles).Fournir un moyen de construire / manipuler des super-packages, c'est-à-dire des packages qui combinent plusieurs packages en un (donc il n'y a qu'un seul élément ajouté
load-path
, un<pkg>-pkg.el
et un<pkg>-autoloads.el
chargé). Cela peut être plus difficile à faire (car vous ne pouvez alors activer qu'une partie des packages contenus dans ces super-packages, donc l'analyse de dépendance / version peut être délicate).La première option ci-dessus devrait être assez facile à implémenter et serait
package-initialize
beaucoup plus rapide lorsque de nombreux packages sont installés. Si cela vous intéresse, n'hésitez pas à me demander de l'aide.FWIW, je viens d'essayer de construire un tel fichier méga-autoloads "à la main" sur ma configuration de test. Résultats: alors que cela
package-initialize
prend environ 0,9s, le chargement dumega-autoloads.el
fichier prend 0,3s que je peux ramener à 0,2s en laissant la liaisonload-source-file-function
à zéro et à 0,1s en compilant le fichier en octets. Je m'attendais à une meilleure accélération, pour être honnête, mais cela en vaut toujours la peine.[EDIT] Cette approche de "méga autochargements" est maintenant disponible dans la branche principale d'Emacs (pour devenir Emacs-27 dans un futur lointain). Il est contrôlé par la nouvelle
package-quickstart
variable.la source
package.el
développeurs. Quel type de conseils avez-vous pour commencer avec cette première option? J'aimerais voir ce que je peux marteler avec, car il semble beaucoup plus réalisable.<pkg>-autoloads.el
fichiers ne configurent que les chargements automatiques et ne se soucient pas de la commande, mais rien ne les empêche de faire d'autres choses au hasard, et package.el garantit que le package dont il<pkg>
dépend sera activé avant<pkg>
lui-même.Le problème que vous décrivez au sujet de
package-initialize
prendre autant de temps à charger est un problème bien connu. C'est également l'un des problèmes que certains frameworks emacs tentent de résoudre en chargeant les chargements automatiques manuellement.Je vois deux solutions à votre problème.
L'une des principales raisons de recommander emacs DOOM est que le framework place la gestion des packages en dehors d'emacs. Ne vous méprenez pas, c'est toujours emacs qui fait la gestion des packages, c'est juste que la gestion des packages se fait en dehors d'une session utilisateur standard. La philosophie est la suivante: lors du démarrage normal d'emacs, nous devrions pouvoir supposer que tous les packages sont présents et peuvent déjà être chargés. Cela fait gagner beaucoup de temps. DOOM emacs fournit une sorte d'équivalent de
apt-get
oupacman
pour emacs. Une fois qu'un paquet est installé, chaque fois qu'emacs démarre, il est supposé être déjà installé; pas de questions posées.la source