¿Qué puedo hacer para acelerar mi arranque?

41

¿Cuáles son algunas cosas básicas que podría hacer para reducir el tiempo de inicio?

¿Hay algo en particular a lo que deba prestar atención?

Nota: El tiempo de inicio se puede mitigar iniciando Emacs con menos frecuencia (una vez por sesión) y abriendo archivos en una instancia en ejecución . Esta pregunta se trata de minimizar el tiempo de inicio, para el inicio de la sesión o en cualquier otro momento en que sea necesario iniciar Emacs.


Vea también la misma pregunta respondida en Stack Overflow, con puntajes de preguntas y respuestas de más de 50 y 30 marcadores favoritos. Las buenas respuestas aquí deberían ir más allá de lo que está disponible en Stack Overflow.

caisah
fuente
1
Me encantaría tener datos sobre esto, pero supongo que para la mayoría de los usuarios hay uno o dos paquetes que representan la mayor parte del tiempo de inicio. En mi caso fue timón. Tenga en cuenta que si usa helm no puede posponer realmente su inicialización, sí quiere que esté listo para usar de inmediato. Cambié a hiedra y eso redujo mi tiempo de inicio de alrededor de 12 segundos a menos de un segundo. Incluso dejé de usar la configuración del servidor / cliente. (Por cierto, no cambié para reducir el tiempo de inicio, eso fue solo un buen beneficio adicional).
Omar

Respuestas:

43

Aquí están mis puntos sobre la reducción emacs-init-time, esto no cubre cosas como usar un demonio o el servidor, no hace falta decir que rara vez debería cerrar emacs.

No:

  • No requiera paquetes en su init, si el paquete no tiene las cookies de carga automática adecuadas, asegúrese de configurar las cargas automáticas en los comandos de entrada. Entonces, si la primera vez que usa el paquete foobarserá llamando foobar-modey foobarno vino precargado automáticamente, necesitará algo como esto:

    (autoload 'foobar-mode "foobar")
    

    esto le permitirá llamar foobar-modeincluso cuando el foobarpaquete aún no se haya cargado. De esta manera foobarno se cargará hasta que realmente llamefoobar-mode

  • No ejecute package-refresh-contentssi no necesita instalar paquetes al inicio. Si su init está configurado para instalar automáticamente paquetes faltantes, considere configurar una línea de comando arg para que especifique cuándo debe realizarse la instalación automática.

  • Como arriba, no haga nada relacionado con la red.
  • No cargue su desktopon init a menos que realmente quiera hacerlo.

Hacer

  • Use algo como use-packageadministrar sus paquetes. Esto facilita la especificación de qué requerir, qué cargar más tarde, qué carga automáticamente y qué perfil facilita su inicio de paquete por paquete.

  • Conozca la diferencia entre cargar un tema y habilitarlo. En resumen, puede cargar tantos como desee, pero asegúrese de no habilitar más de uno. Idealmente, solo carga y habilita un tema. load-themenecesita un argumento opcional para evitar la habilitación del tema. Puede ser fácil habilitar accidentalmente varios temas, lo que es lento y feo durante el inicio.

  • Hacer trampa: a menudo hay modos globales grandes que querrás cargar en init, cosas como deshacer el árbol, autocompletar, modo id, etc. . Hago esto undo-tree-mode, idoy otros, y nunca noto un retraso porque para cuando realmente necesito usarlos, ya están cargados.

    Actualización: use-package ha cambiado un poco, lea el archivo Léame oficial antes de comenzar a usar las funciones del temporizador.

    Por ejemplo: si desea retrasar un poco la carga global-undo-tree-mode, puede poner esto en su init:

    (run-with-idle-timer 1 nil (lambda () (global-undo-tree-mode t)))
    

    Ahora su init puede continuar felizmente y global-undo-tree-modeno se activará hasta que todo lo demás esté listo y usted esté detrás del volante.

    use-packagetiene soporte para este tipo de comportamiento integrado usando la palabra clave: idle. Aquí está la undo-treeconfiguración de mi .init.el:

    (use-package undo-tree
      :idle (global-undo-tree-mode 1)
      :bind (("C-c j" . undo-tree-undo)
             ("C-c k" . undo-tree-redo)
             ("C-c l" . undo-tree-switch-branch)
             ("C-c ;" . undo-tree-visualize))
      :ensure t)
    
  • Perfile su init, siempre es sorprendente ver dónde están las verdaderas ralentizaciones. profile-dotemacs.el es una herramienta increíble que he usado para ayudarme a bajar mi inicio de ~ 6 segundos a <1 segundo.

Un use-packageinit bien configurado puede ser increíblemente rápido. No compilo en bytes mi init y se usa use-packagepara configurar 95 paquetes y se inicia en <1 segundo.

Jordon Biondo
fuente
77
"Perfile su init, siempre es sorprendente ver dónde están las verdaderas ralentizaciones". Alerta de spoiler, es esa (require 'org)línea. :-)
Malabarba
@ Jordania, ¿podría ampliar un poco cómo se asegura de que las funciones de entrada tengan configuración de carga automática y luego iniciar temporizadores inactivos en su init para cargar los paquetes, en particular para el modo deshacer árbol? Gracias.
Francisco Dibar
@FranciscoDibar He actualizado mi publicación con ejemplos.
Jordon Biondo
2
Uso el modo ido de inmediato, Cx Cf o Mx para smex es lo primero que hago casi siempre cuando abro emacs, y nunca he notado un problema. Además, si desea deshacer algo dentro de un segundo de abrir emacs ... Bueno, no tengo nada que decir al respecto. Si realmente le preocupa, pruébelo usted mismo, o simplemente use un temporizador que no esté inactivo o después del gancho de inicio.
Jordon Biondo
1
La sugerencia de temporizador inactivo es útil. Una sintaxis de carga un poco más corta es (run-with-idle-timer 1 nil #'global-undo-tree-mode)'. If the function you are loading takes parameters you can just provide them after the el comando # ''.
Andrew Swann
8

Algo que apareció recientemente en emacs reddit : disminuya el número de invocaciones de recolección de basura colocando esto cerca del comienzo de su archivo init:

(setq gc-cons-threshold 50000000)

(add-hook 'emacs-startup-hook 'my/set-gc-threshold)
(defun my/set-gc-threshold ()
  "Reset `gc-cons-threshold' to its default value."
  (setq gc-cons-threshold 800000))

En el ejemplo anterior, el GC se invoca cada ~ 50 MB (en lugar del valor predeterminado de ~ 800 kb), lo que parece razonable en un sistema moderno con mucha RAM.

ffevotte
fuente
1
Excepto que el valor es (a) probablemente mucho más alto de lo que necesita (no veo diferencia con una décima parte de eso); y (b) evidentemente no es un valor que desea persistir más allá del inicio, porque un umbral de GC grande equivale a demoras más largas cada vez que ocurre GC. Si lo configura alto para init, vuelva a configurarlo más bajo después de init. Creo que emacs-startup-hookes un buen lugar para hacer eso.
phils
1
@phils Gracias! (a) En mi configuración, 50Mb proporciona la cantidad mínima de GC (y el tiempo mínimo de inicio). Si voy tan bajo como 10Mb, la diferencia es notable / medible (aunque no cambia mucho en la práctica ...) (b) buena idea, gracias. Edité la publicación para reflejar su comentario.
ffevotte
6

El tiempo que pasa optimizando su tiempo de inicio probablemente será mayor que todo el tiempo extra que de otro modo hubiera esperado a que Emacs se iniciara.

En este momento hago 25 requirellamadas en mi archivo init para que Flycheck pueda encontrar errores ortográficos en mi código. Mi tiempo de inicio es ...

$ time emacs --eval '(save-buffers-kill-terminal)'

real    0m2.776s
user    0m2.305s
sys     0m0.148s

Además, en mi sistema, time emacs -Q --eval '(save-buffers-kill-terminal)'tiene una realde 0m0.404s. La cantidad máxima teórica de tiempo que puedo ahorrar es de 2,3 segundos.

Digamos que paso una hora haciendo todo tipo de optimizaciones en mi archivo de inicio. (No contaré los 15-30 minutos adicionales que pasé en una fecha posterior tratando de averiguar por qué mis cambios no entraron en vigencia debido a que mi archivo init se compila en bytes). (Tampoco contaré el tiempo que Flycheck me habría salvado en el depurador si no hubiera eliminado las requirellamadas.) Hay 3600 segundos en una hora, por lo que si lograra ahorrar los 2.3 segundos completos, mi inversión en tiempo solo se amortizaría después de 1565 inicios.

Suponiendo que reiniciara Emacs 3 veces al día, todos los días, tomaría un año y medio para que esa inversión valga la pena. Si dejara la misma instancia de Emacs ejecutándose durante días (como lo hago a menudo), probablemente solo reiniciaría de 2 a 5 veces por semana, en cuyo caso tomaría entre 6 y 15 años para que esa inversión valga la pena.

Estoy siendo generoso, porque es probable que pases más de una hora optimizando tu inicio, y probablemente no guardarás la cantidad máxima teórica de segundos.

Jackson
fuente
12
Pero potencialmente serás más feliz.
Phil
2
Eso puede ser cierto para una persona, pero el objetivo de StackExchange es compartir. ¿Qué tal un truco que toma 30 minutos para que una persona lo encuentre, pero reduce 1 segundo del tiempo de inicio de docenas de personas? ¿Todavía lo considerarías una mala inversión?
ffevotte
@phils Irónicamente, consideré decir lo mismo, ¡pero en apoyo de mi propio punto de vista! "Antes de quejarse de su tiempo de inicio, piense: '¡Me alegra no haber perdido el tiempo optimizando esto!'"
Jackson,
@Francesco Y esta publicación es mi truco que ahorra tiempo a docenas de personas.
Jackson
@Jackson Todavía no estoy de acuerdo contigo en este tema en particular, pero al menos ahora entiendo tu punto. Gracias :)
ffevotte