Cosa posso fare per accelerare il mio avvio?


41

Quali sono alcune cose di base che potrei fare per ridurre i tempi di avvio?

C'è qualcosa in particolare a cui dovrei prestare attenzione, del resto?

Nota: il tempo di avvio può essere mitigato avviando Emacs meno spesso (una volta per sessione) e aprendo i file in un'istanza in esecuzione . Questa domanda riguarda la riduzione al minimo del tempo di avvio, per l'avvio della sessione o in qualsiasi altro momento in cui è necessario avviare Emacs.


Vedi anche la stessa domanda con risposta su Stack Overflow, con punteggi di domande e risposte su 50 e 30-alcuni segnalibri "preferiti". Le buone risposte qui dovrebbero andare oltre ciò che è disponibile su StackTranslate.it.


1
Mi piacerebbe avere dati su questo, ma la mia ipotesi è che per la maggior parte degli utenti ci siano uno o due pacchetti che rendono la maggior parte del tempo di avvio. Nel mio caso era il timone. Nota che se usi helm non puoi davvero posticipare la sua inizializzazione, lo vuoi subito pronto per l'uso. Sono passato all'edera e questo ha portato il mio orario di partenza da circa 12 secondi a meno di un secondo. Ho persino smesso di usare la configurazione server / client. (A proposito, non sono passato a ridurre i tempi di avvio, è stato solo un bel vantaggio collaterale.)
Omar,

Risposte:


43

Ecco i miei punti sulla riduzione emacs-init-time, questo non copre cose come l'uso di un demone o del server, va da sé che raramente si dovrebbe mai chiudere emacs.

Non:

  • Non richiedere pacchetti nel tuo init, se il pacchetto non ha i cookie di caricamento automatico adeguati, assicurati di impostare i caricamenti automatici sui comandi di inserimento. Quindi, se la prima volta che utilizzi il pacchetto foobarsarà chiamando foobar-modee foobarnon fosse arrivato pre-caricato automaticamente avrai bisogno di qualcosa del genere:

    (autoload 'foobar-mode "foobar")
    

    questo ti permetterà di chiamare foobar-modeanche quando il foobarpacchetto non è stato ancora caricato. In questo modo foobarnon verrà caricato fino a quando non si chiama effettivamentefoobar-mode

  • Non eseguire package-refresh-contentsse non è necessario installare i pacchetti all'avvio. Se init è configurato per l'installazione automatica di pacchetti mancanti, prendere in considerazione la possibilità di impostare un arg della riga di comando per specificare quando deve avvenire l'installazione automatica.

  • Come sopra, non fare nulla relativo alla rete.
  • Non caricare il tuo desktopinit se non lo vuoi davvero.

Fare

  • Usa qualcosa di simile use-packageper gestire i tuoi pacchetti. Ciò semplifica la specifica di cosa richiedere, cosa caricare in seguito, cosa caricare automaticamente cosa e rendere semplice la profilatura di init su un pacchetto per pacchetto.

  • Conosci la differenza tra caricare un tema e abilitarlo. In breve, puoi caricarne quanti ne vuoi, ma assicurati di non abilitarne più di uno. Idealmente, carica e abilita solo un tema. load-themeha bisogno di un argomento opzionale per impedire l'abilitazione del tema. Può essere facile abilitare accidentalmente più temi, che è lento e brutto durante l'avvio.

  • Trucchi: ci sono spesso grandi modalità globali che vorrai caricare su init, cose come annulla struttura, completamento automatico, modalità ido ecc. Assicurati che le funzioni di immissione abbiano l'impostazione di caricamenti automatici quindi avvia i timer di inattività nel tuo init per caricare i pacchetti . Faccio questo undo-tree-mode, idoe altri e non noto mai un ritardo perché quando ho davvero bisogno di usarli, sono già caricati.

    Aggiornamento: use-package è cambiato un po ', leggi il readme ufficiale prima di iniziare a usare le funzionalità del timer.

    Ad esempio: se volessi ritardare leggermente il caricamento global-undo-tree-modepotresti metterlo nel tuo init:

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

    Ora il tuo init può continuare felicemente e global-undo-tree-modein realtà non verrà attivato fino a quando tutto il resto sarà pronto e sarai al volante.

    use-packageha il supporto per questo tipo di comportamento integrato usando la parola chiave: idle. Ecco la undo-treeconfigurazione dal mio .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)
    
  • Profila il tuo init, è sempre sorprendente vedere dove sono i veri rallentamenti. profile-dotemacs.el è uno strumento incredibile che ho usato per aiutarmi a ridurre il mio init da ~ 6 secondi a <1 secondo.

Un use-packageinit ben configurato può essere incredibilmente veloce. Non compilo byte il mio init e lo usa use-packageper configurare 95 pacchetti e si avvia in <1 secondo.


7
"Profila il tuo init, è sempre sorprendente vedere dove sono i veri rallentamenti." Avviso spoiler, è quella (require 'org)linea. :-)
Malabarba,

@Jordan, potresti estendere un po 'il modo in cui assicuri che le funzioni di immissione abbiano impostazioni di caricamento automatico e poi avvii i timer inattivi nel tuo init per caricare i pacchetti, in particolare per la modalità di annullamento dell'albero? Grazie.
Francisco Dibar,

@FranciscoDibar Ho aggiornato il mio post con esempi.
Jordon Biondo,

2
Uso immediatamente la modalità ido, Cx Cf o Mx per smex è la prima cosa che quasi sempre quando apro emacs e non ho mai notato un problema. Anche se vuoi annullare qualcosa entro un secondo dall'apertura di emacs ... Beh, non ho nulla da dire al riguardo. Se sei davvero così preoccupato, provalo tu stesso, o semplicemente usa un timer non inattivo o dopo il hook di init.
Jordon Biondo,

1
Il suggerimento del timer di inattività è utile. Una sintassi di caricamento leggermente più breve è il (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 comando # ''.
Andrew Swann,

8

Qualcosa che recentemente è emerso su emacs reddit : ridurre il numero di invocazioni della garbage collection mettendo questo vicino all'inizio del file 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))

Nell'esempio sopra, il GC viene invocato ogni ~ 50 MB (invece del valore predefinito di ~ 800kb), il che sembra ragionevole su un sistema moderno con molta RAM.


1
Solo che quel valore è (a) probabilmente molto più alto del necessario (non vedo alcuna differenza con un decimo di quello); e (b) evidentemente non è un valore che si desidera persistere oltre l'avvio, poiché una soglia GC elevata equivale a ritardi più lunghi ogni volta che si verifica GC. Se lo si imposta in alto per init, riportarlo nuovamente in basso dopo init. Penso che emacs-startup-hooksia un buon posto per farlo.
phils,

1
@phils Grazie! (a) Nella mia configurazione, 50 Mb forniscono il numero minimo di GC (e il tempo minimo di avvio). Se vado fino a 10 Mb, la differenza è evidente / misurabile (anche se in pratica non cambia molto ...) (b) buona idea, grazie. Ho modificato il post per riflettere il tuo commento.
ffevotte,

6

Il tempo impiegato per ottimizzare il tempo di avvio sarà probabilmente maggiore di tutto il tempo extra che altrimenti avresti aspettato per l'avvio di Emacs.

Al momento faccio 25 requirechiamate nel mio file init in modo che Flycheck possa trovare errori di ortografia nel mio codice. Il mio tempo di avvio è ...

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

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

Inoltre, sul mio sistema, time emacs -Q --eval '(save-buffers-kill-terminal)'ha un realdi 0m0.404s. Il tempo massimo teorico che posso risparmiare è di 2,3 secondi.

Supponiamo che passi un'ora a fare tutte le ottimizzazioni per il mio file init. (Non conterò i 15-30 minuti aggiuntivi trascorsi in un secondo momento nel tentativo di capire perché le mie modifiche non hanno avuto effetto a causa della compilazione del mio file init.) (Inoltre non conterò il tempo che Flycheck mi avrebbe salvato nel debugger se non avessi rimosso le requirechiamate.) Ci sono 3600 secondi in un'ora, quindi se riuscissi a salvare gli interi 2,3 secondi, il mio investimento nel tempo sarebbe ripagato solo dopo 1565 startup.

Supponendo che ho riavviato Emacs 3 volte al giorno, ogni giorno, ci vorrebbe un anno e mezzo perché quell'investimento ripaghi. Se avessi lasciato la stessa istanza di Emacs in esecuzione per giorni alla volta (come faccio spesso), probabilmente ricomincerei solo 2-5 volte a settimana, nel qual caso occorrerebbero dai 6 ai 15 anni per ripagare tale investimento.

Sono generoso, perché probabilmente passerai più di un'ora a ottimizzare la tua startup e probabilmente non risparmierai il massimo numero teorico di secondi.


12
Ma sarai potenzialmente più felice.
phils,

2
Questo può essere vero per una persona, ma l'intero punto di StackExchange riguarda la condivisione. Che ne dici di un trucco che impiega 30 minuti per essere trovato da una persona, ma riduce di 1 secondo il tempo di avvio di dozzine di persone? Lo considereresti comunque un cattivo investimento?
ffevotte,

@phils Ironicamente, ho pensato di dire la stessa cosa, ma a sostegno del mio punto di vista! "Prima di lamentarti del tuo tempo di avvio, pensa a te stesso, 'Sono contento di non aver perso tempo a ottimizzare questo!'"
Jackson,

@Francesco E questo post è il mio trucco che fa risparmiare tempo a dozzine di persone.
Jackson,

@Jackson Non sono ancora d'accordo con te su questo particolare problema, ma almeno ora vedo il tuo punto. Grazie :)
ffevotte,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.