Was kann ich tun, um meinen Start zu beschleunigen?

41

Was kann ich tun, um die Startzeit zu verkürzen?

Gibt es etwas, auf das ich besonders achten sollte?

Hinweis: Die Startzeit kann verkürzt werden, indem Emacs weniger häufig gestartet wird (einmal pro Sitzung) und Dateien in einer laufenden Instanz geöffnet werden . Bei dieser Frage geht es um die Minimierung der Startzeit, für den Sitzungsstart oder um eine andere Zeit, zu der das Starten von Emacs erforderlich ist.


Siehe auch die gleiche Frage , die auf Stack Overflow beantwortet wurde, mit Frage-und-Antwort-Punktzahlen über 50 und 30 - einige "Lieblings" -Lesezeichen. Gute Antworten sollten über das hinausgehen, was bei Stack Overflow verfügbar ist.

caisah
quelle
1
Ich würde gerne Daten darüber haben, aber ich vermute, dass es für die meisten Benutzer ein oder zwei Pakete gibt, die den Großteil der Startzeit ausmachen. In meinem Fall war es das Ruder. Wenn Sie helm verwenden, können Sie die Initialisierung nicht wirklich verschieben, sondern möchten, dass es sofort einsatzbereit ist. Ich habe auf Efeu umgestellt und meine Startzeit hat sich von ungefähr 12 Sekunden auf weniger als eine Sekunde verringert. Ich habe sogar aufgehört, das Server / Client-Setup zu verwenden. (Übrigens habe ich nicht gewechselt, um die Startzeit zu verkürzen, das war nur ein netter Nebeneffekt.)
Omar

Antworten:

43

Hier sind meine Punkte zum Reduzieren emacs-init-time: Dies gilt nicht für die Verwendung eines Daemons oder des Servers. Es versteht sich von selbst, dass Sie Emacs selten schließen sollten.

Nicht:

  • Sie benötigen keine Pakete in Ihrem Init. Wenn das Paket keine richtigen Autoload-Cookies enthält, stellen Sie sicher, dass Sie Autoloads für die Eingabebefehle einrichten. Wenn Sie das Paket also zum ersten Mal verwenden foobar, indem Sie anrufen foobar-modeund foobares nicht vorinstalliert wurde, benötigen Sie Folgendes:

    (autoload 'foobar-mode "foobar")
    

    Auf diese Weise können Sie auch dann anrufen foobar-mode, wenn das foobarPaket noch nicht geladen wurde. Dieser Weg foobarwird erst geladen, wenn Sie tatsächlich anrufenfoobar-mode

  • Führen package-refresh-contentsSie das Programm nicht aus, wenn Sie beim Start keine Pakete installieren müssen. Wenn Sie init so einrichten, dass fehlende Pakete automatisch installiert werden, sollten Sie ein Befehlszeilenargument einrichten, das angibt, wann die automatische Installation erfolgen soll.

  • Machen Sie wie oben nichts mit dem Netzwerk zu tun.
  • Laden Sie Ihr desktopon init nur, wenn Sie es wirklich wollen.

Machen

  • Verwenden Sie etwas wie use-packagezum Verwalten Ihrer Pakete. Auf diese Weise können Sie auf einfache Weise festlegen, was erforderlich ist, was später geladen werden soll, was automatisch geladen wird und das Profilieren Ihres Init für jedes Paket einfach gestalten.

  • Erkennen Sie den Unterschied zwischen dem Laden und dem Aktivieren eines Themas. Kurz gesagt, Sie können so viele laden, wie Sie möchten, stellen Sie jedoch sicher, dass Sie nicht mehr als eine aktivieren. Im Idealfall laden und aktivieren Sie nur ein Thema. load-themeBenötigt ein optionales Argument, um das Aktivieren des Themas zu verhindern. Es kann leicht sein, versehentlich mehrere Themen zu aktivieren, was beim Start langsam und hässlich ist.

  • Betrügen Sie: Es gibt oft große globale Modi, die Sie auf init laden möchten, z. B. Undo-Tree, Autocomplete, Ido-Mode usw. Stellen Sie sicher, dass die Eingabefunktionen über Autoloads-Setup verfügen, und starten Sie in Ihrem init Leerlauf-Timer, um die Pakete zu laden . Ich mache diesen Willen undo-tree-mode, idound andere , und nie eine Verzögerung feststellen , weil durch die Zeit , die ich brauche wirklich , sie zu nutzen, werden sie bereits geladen.

    Update: use-package hat sich etwas geändert. Lesen Sie die offizielle Readme-Datei, bevor Sie die Timer-Funktionen verwenden.

    Zum Beispiel: Wenn Sie das Laden von etwas verzögern möchten, können global-undo-tree-modeSie dies in Ihr Init einfügen:

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

    Jetzt kann Ihr init glücklich weitermachen und global-undo-tree-modewird erst dann aktiviert, wenn alles andere bereit ist und Sie sich ans Steuer setzen.

    use-packagehat Unterstützung für diese Art von Verhalten mit dem Schlüsselwort: idle eingebaut. Hier ist die undo-treeKonfiguration von meinem .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)
    
  • Wenn Sie Ihre Init profilieren, ist es immer wieder überraschend zu sehen, wo die wirklichen Verlangsamungen liegen. profile-dotemacs.el ist ein unglaubliches Tool, mit dessen Hilfe ich mein Init von ~ 6 Sekunden auf <1 Sekunde verringert habe.

Ein gut konfigurierter use-packageInit kann unglaublich schnell sein. Ich kompiliere mein Init nicht byteweise und es wird use-packagezum Konfigurieren von 95 Paketen verwendet und startet in <1 Sekunde.

Jordon Biondo
quelle
7
"Machen Sie ein Profil Ihrer Init, es ist immer wieder überraschend zu sehen, wo die wirklichen Verlangsamungen liegen." Spoiler Alarm, das ist die (require 'org)Linie. :-)
Malabarba
@Jordan, könntest du bitte etwas näher erläutern, wie du sicherstellst, dass für die Eingabefunktionen Autloads eingerichtet sind, und dann in deinem Init Idle-Timer starten, um die Pakete zu laden, insbesondere für den Undo-Tree-Modus? Vielen Dank.
Francisco Dibar
@FranciscoDibar Ich habe meinen Beitrag mit Beispielen aktualisiert.
Jordon Biondo
2
Ich benutze sofort den Ido-Modus, Cx Cf oder Mx für smex ist das erste, was ich fast immer beim Öffnen von Emacs habe, und ich habe noch nie ein Problem bemerkt. Auch wenn Sie innerhalb einer Sekunde nach dem Öffnen von Emacs etwas rückgängig machen möchten ... Nun, dazu habe ich nichts zu sagen. Wenn Sie wirklich so besorgt sind, probieren Sie es selbst aus, oder verwenden Sie einfach einen nicht inaktiven Timer oder nach dem Init-Hook.
Jordon Biondo
1
Der Vorschlag für den Leerlaufzeitgeber ist nützlich. Eine etwas kürzere Ladesyntax ist (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 # '`command.
Andrew Swann
8

Etwas, das kürzlich auf emacs reddit aufgetaucht ist : Verringern Sie die Anzahl der Garbage Collection-Aufrufe, indem Sie Folgendes an den Anfang Ihrer Init-Datei setzen:

(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))

Im obigen Beispiel wird der GC alle ~ 50 MB (anstelle des Standardwerts von ~ 800 KB) aufgerufen, was auf einem modernen System mit viel RAM sinnvoll erscheint.

ffevotte
quelle
1
Mit der Ausnahme, dass der Wert (a) wahrscheinlich viel höher ist als Sie benötigen (ich sehe keinen Unterschied zu einem Zehntel davon); und (b) offensichtlich kein Wert, den Sie nach dem Start beibehalten möchten, da ein großer GC-Schwellenwert längeren Verzögerungen entspricht, wenn GC auftritt. Wenn Sie für init einen hohen Wert einstellen, stellen Sie ihn nach init wieder auf einen niedrigeren Wert zurück. Ich denke, das emacs-startup-hookist ein guter Ort, um das zu tun.
Phils
1
@phils Danke! (a) Bei meinem Setup geben 50 MB die minimale Anzahl von GCs (und die minimale Startzeit) an. Wenn ich auf nur 10 MB gehe, ist der Unterschied spürbar / messbar (obwohl sich in der Praxis nicht viel ändert ...) (b) Gute Idee, danke. Ich habe den Beitrag bearbeitet, um Ihren Kommentar wiederzugeben.
ffevotte
6

Die Zeit, die Sie für die Optimierung Ihrer Startzeit aufwenden, ist wahrscheinlich länger als die gesamte zusätzliche Zeit, die Sie sonst auf den Start von Emacs gewartet hätten.

Momentan requirerufe ich 25 Mal in meiner Init-Datei auf, damit Flycheck Rechtschreibfehler in meinem Code findet. Meine Startzeit ist ...

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

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

Auch auf meinem System time emacs -Q --eval '(save-buffers-kill-terminal)'hat ein realvon 0m0.404s. Die theoretische maximale Zeitersparnis beträgt 2,3 Sekunden.

Angenommen, ich verbringe eine Stunde damit, alle Optimierungen an meiner Init-Datei vorzunehmen. (Ich zähle die zusätzlichen 15-30 Minuten, die für einen späteren Zeitpunkt aufgewendet wurden, nicht, um herauszufinden, warum meine Änderungen nicht wirksam wurden, weil meine Init-Datei bytekompiliert wurde.) (Ich zähle auch nicht die Zeit dafür Flycheck hätte mich im Debugger gerettet, wenn ich die requireAnrufe nicht entfernt hätte .) Eine Stunde hat 3600 Sekunden. Wenn ich also die gesamten 2,3 Sekunden einsparen könnte, würde sich meine Zeitinvestition erst nach 1565 Starts auszahlen.

Angenommen, ich habe Emacs dreimal am Tag neu gestartet, dann dauerte es anderthalb Jahre, bis sich diese Investition amortisiert hatte. Wenn ich dieselbe Emacs-Instanz tagelang laufen lassen würde (wie ich es oft tue), würde ich wahrscheinlich nur 2-5 Mal pro Woche neu starten. In diesem Fall würde es 6 bis 15 Jahre dauern, bis sich diese Investition auszahlt.

Ich bin großzügig, weil Sie wahrscheinlich mehr als eine Stunde damit verbringen, Ihr Startup zu optimieren, und Sie werden wahrscheinlich nicht die maximale theoretische Anzahl von Sekunden sparen.

Jackson
quelle
12
Aber Sie werden möglicherweise glücklicher sein.
Phils
2
Das mag für eine Person zutreffen, aber bei StackExchange dreht sich alles um das Teilen. Was ist mit einem Trick, der 30 Minuten dauert, bis eine Person ihn gefunden hat, der jedoch die Startzeit von Dutzenden von Personen um 1 Sekunde verkürzt? Würden Sie es immer noch für eine schlechte Investition halten?
ffevotte
@phils Ironischerweise dachte ich darüber nach, dasselbe zu sagen, aber zur Unterstützung meiner eigenen Sichtweise! "Bevor Sie über Ihre Startzeit stöhnen, denken Sie sich: Ich bin froh, dass ich keine Zeit damit verschwendet habe, diese zu optimieren!"
Jackson
@Francesco Und dieser Beitrag ist mein Trick, der Dutzenden von Menschen Zeit spart.
Jackson
@Jackson Ich stimme dir in diesem Punkt immer noch nicht zu, aber zumindest verstehe ich jetzt deinen Standpunkt. Danke :)
ffevotte