TL; DR Tengo una cantidad tan grande de paquetes que está perjudicando mi tiempo de inicio. Si no crees que ese podría ser el caso, sigue leyendo.
Mi tiempo de inicio de Emacs es bastante pequeño. No lo uso use-package
, solo configuro toneladas de ganchos y autoload
s para que se difiera casi todo el código. En realidad, todo se carga en menos de medio segundo, a pesar de que parece un desastre loco.
Sin embargo, con el tiempo me di cuenta de que mi tiempo de inicio se pone minuciosamente más lenta, inexplicablemente. Esto finalmente ha llegado al punto donde el tiempo de inicio es ≥ 1 segundo. Finalmente tuve suficiente y profundicé en la raíz del problema. Finalmente comenté todo mi ~/.emacs
archivo y descubrí que el tiempo de inicio todavía era ≥ 1 segundo. De hecho, solo se había reducido ~ 0.2
segundos, a veces incluso menos. Luego intenté emacs -q
y descubrí que el tiempo de inicio era de ~ 0.1
segundos.
Al examinar esta sección del manual de Elisp, descubrí por qué emacs -q
estaba reduciendo tanto el tiempo de inicio. Aparentemente emacs -q
impide que Emacs haga tres cosas al inicio:
- cargando su archivo de inicio
- cargando su
default.el
archivo - vocación
package-initialize
Ya hemos descartado mi archivo de inicio, ya que comentar todo ~/.emacs
no hace casi nada. No uso un default.el
archivo, por lo que también se descarta. Lo que deja package-initialize
como el culpable del éxito de rendimiento.
¿Por qué estaría package-initialize
tomando tanto tiempo de inicio? Esa fue la primera pregunta que me hice. ¿No estoy cargando todo automáticamente? Bueno, sí. Pero ese es precisamente el problema.
Encontré esta publicación que explica que "activar" paquetes consiste en leer archivos de carga automática y establecer rutas de carga. Obviamente, esto incurre en una penalización de E / S cuando tiene muchos paquetes porque tiene muchos archivos de carga automática para leer y muchas rutas para configurar. Desafortunadamente, sin esto, la tarea de administrar las cargas automáticas cae en manos del usuario. En otras palabras, sin dejar que package.el
rastree el sistema de archivos para la carga automática de archivos y rutas, tendría que administrarlo yo mismo, lo que podría ser un proceso tedioso y propenso a errores.
Preferiría no ir por ese camino. Actualmente tengo 116 paquetes, de los cuales 107 son de ELPA y 25 de los cuales son dependencias. Estoy seguro de que este enorme número es lo que está degradando tanto mi rendimiento. Pero estoy en un dilema porque no quiero eliminar ninguno de mis paquetes.
¿Existe algún remedio en tal situación para recuperar el tiempo de inicio de mi rayo?
Actualizar:
Hemos comenzado un nuevo hilo en la emacs-devel
lista de correo sobre algunos parches de Stefan Monnier (una descripción de estos parches está aquí ) para resolver este problema. Cualquiera puede probar sus parches y dar su opinión.
Otra actualización:
Parece que Stefan Monnier ya no está interesado en este problema o no está recibiendo mis mensajes. Me inclino a creer lo primero, lo cual está bien, aunque agradecería algún tipo de respuesta de él si ese fuera el caso. De todos modos, el código que ha producido para este problema hasta ahora funciona bastante bien. Los parches más recientes suyos se pueden encontrar aquí (para Emacs 25.3) y aquí (para la rama maestra de Emacs).He visto buenas mejoras en mi tiempo de inicio gracias a sus parches y estoy en un punto en el que me siento cómodo con mi tiempo de inicio de tal manera que esté lo más optimizado posible sin eliminar las características de mi personalización. Esperaba que estos parches llegaran a la línea principal de Emacs en algún momento, pero supongo que yo (o alguien más) tendría que tomar la antorcha ahora, en lugar de Stefan. Tuvimos un poco de discusión en la lista de correo sobre asignación de derechos de autor y licencias. Inicialmente me sentí incómodo al hacerlo, pero debido a algunos comentarios de Richard Stallman y otros, la asignación de derechos de autor puede no ser tan restrictiva como pensaba originalmente. Además, es posible que pueda comprometer mis trabajos al dominio público como una alternativa a la asignación de derechos de autor.
En cualquier caso, ¡gracias Stefan por los parches hasta ahora! Espero que continúes desarrollando estos cambios, pero si no, está bien y puedo continuar desarrollándolo en algún momento. También agradezco a todos los demás que ofrecieron información y contribución para resolver este problema.
Otra actualización más:
Wow, parece que esta característica finalmente aterrizó y estará en Emacs 27. ¡Gracias a Stefan Monnier!
use-package
es el camino a seguir para esto.Respuestas:
Una de las opciones de diseño en package.el era intentar hacer las cosas "simples". Parte de esto es que
package-initialize
busca todos los paquetes que están instalados, luego trata de averiguar cuáles de ellos deben activarse (de acuerdo con la fijación y la antigüedad de las versiones en caso de que estén disponibles varias versiones del mismo paquete), luego carga cada uno activa el<pkg>-autoloads.el
archivo del paquete .Entonces, para N paquetes instalados, eso significa básicamente leer N
<pkg>-pkg.el
archivos de descripción de paquete y N<pkg>-autoloads.el
archivos. Para N grandes, eso puede convertirse en un problema grave. Otro posible problema de rendimiento es que agregará N elementosload-path
, por lo que cada vez queload
Emacs busque a través de N directorios, cada unoload
se ralentizará.Hay varias formas en que podemos intentar acelerar esto:
Proporcione alguna forma de calcular previamente un
~/.emacs.d/elpa/package-initialize.el(c)
archivo que sería el resultado de concatenar todo<pkg>-autoloads.el
en el orden correcto. Entoncespackage-initialize
podría cargar este archivo cuando esté presente y omitir todo lo demás. Luego, necesitaría alguna forma de actualizar / vaciar elpackage-initialize.el(c)
archivo cuando se agregan / actualizan / eliminan paquetes o cuando cambia supackage-pinned-packages
o supackage-load-list
. Creo que esto se puede hacer con muy pocos cambios en el sistema (creo que lo único que realmente necesitaría cambiar espackage-initialize
para que se le pueda decir que "solo se active" sin cargar los metadatos sobre los paquetes disponibles).Proporcione alguna forma de construir / manipular superpaquetes, es decir, paquetes que combinan varios paquetes en uno (por lo que solo se agrega un elemento
load-path
, uno<pkg>-pkg.el
y uno<pkg>-autoloads.el
cargado). Esto podría ser más difícil de hacer (porque entonces no puede activar solo una parte de los paquetes contenidos en dichos superpaquetes, por lo que el análisis de dependencia / versión podría ser complicado).La primera opción anterior debería ser bastante fácil de implementar y sería
package-initialize
mucho más rápida cuando tenga muchos paquetes instalados. Si está interesado en probar esto, no dude en pedirme ayuda.FWIW, acabo de intentar construir un archivo de megacargas automáticas "a mano" en mi configuración de prueba. Resultados: mientras
package-initialize
toma alrededor de 0.9s, la carga delmega-autoloads.el
archivo toma 0.3s que puedo reducir a 0.2s al vincularload-source-file-function
a cero, y a 0.1s al compilar el archivo en bytes. Esperaba una mejor velocidad, para ser honesto, pero aún así vale la pena.[EDITAR] Este enfoque de "megacargas automáticas" ahora está disponible en la rama maestra de Emacs (para convertirse en Emacs-27 en un futuro lejano). Está controlado por la nueva
package-quickstart
variable.fuente
package.el
desarrolladores. ¿Qué tipo de consejo tienes para comenzar con esa primera opción? Me gustaría ver qué puedo hacer con él, ya que parece mucho más viable.<pkg>-autoloads.el
archivos solo configuran las cargas automáticas y, de hecho, no les importa ordenar, pero no hay nada que les impida hacer otras cosas al azar, y package.el garantiza que el paquete del que<pkg>
depende se activará antes que él<pkg>
mismo.El problema que describe sobre
package-initialize
tomar tanto tiempo para cargar es un problema bien conocido. También es uno de los problemas que algunos frameworks de emacs intentan resolver cargando las cargas automáticas manualmente.Veo dos soluciones a tu problema.
Una de las principales razones para recomendar DOOM emacs es que el marco coloca la administración de paquetes fuera de emacs. No me malinterpreten, todavía es emacs el que gestiona los paquetes, es solo que la gestión de paquetes se realiza fuera de una sesión de usuario estándar. La filosofía aquí es: cuando normalmente se inicia emacs, deberíamos poder suponer que todos los paquetes están presentes y que ya se pueden cargar. Esto ahorra mucho tiempo. DOOM emacs proporciona una especie del equivalente de
apt-get
opacman
para emacs. Una vez que se instala un paquete, cada vez que se inicia emacs se supone que ya está instalado; no se hicieron preguntas.fuente