Co mogę zrobić, aby przyspieszyć mój start-up?

41

Co mogę zrobić, aby skrócić czas uruchamiania?

Czy jest coś szczególnego, na co powinienem zwrócić uwagę?

Uwaga: Czas uruchamiania można ograniczyć, rzadziej uruchamiając Emacsa (raz na sesję) i otwierając pliki w działającej instancji . To pytanie dotyczy zminimalizowania czasu uruchamiania, rozpoczęcia sesji lub w dowolnym innym momencie, gdy konieczne jest uruchomienie Emacsa.


Zobacz także to samo pytanie, na które odpowiedziano na temat Przepełnienia stosu, z wynikami pytań i odpowiedzi powyżej 50 i 30-niektórych „ulubionych” zakładek. Dobre odpowiedzi tutaj powinny wykraczać poza to, co jest dostępne w przepełnieniu stosu.

caisah
źródło
1
Chciałbym mieć dane na ten temat, ale domyślam się, że dla większości użytkowników jest jeden lub dwa pakiety, które stanowią większość czasu uruchamiania. W moim przypadku był to hełm. Pamiętaj, że jeśli używasz steru, tak naprawdę nie możesz odroczyć jego inicjalizacji, chcesz, aby był on gotowy do użycia od razu. Zmieniłem na bluszcz, co skróciło mój czas rozpoczęcia z około 12 sekund do mniej niż sekundy. Nawet przestałem używać konfiguracji serwer / klient. (Nawiasem mówiąc, nie przestawiłem się na skrócenie czasu uruchamiania, to była po prostu miła dodatkowa korzyść.)
Omar

Odpowiedzi:

43

Oto moje uwagi na temat zmniejszania emacs-init-time, nie obejmuje to takich rzeczy jak używanie demona lub serwera, nie trzeba dodawać, że rzadko powinieneś zamykać emacsa.

Nie:

  • Nie wymagaj pakietów w swoim init, jeśli pakiet nie ma odpowiednich plików cookie z automatycznym ładowaniem, upewnij się, że skonfigurowałeś automatyczne ładowanie dla poleceń wejściowych. Jeśli więc po raz pierwszy użyjesz pakietu foobar, dzwoniąc foobar-modei foobarnie był on wstępnie ładowany automatycznie, potrzebujesz czegoś takiego:

    (autoload 'foobar-mode "foobar")
    

    pozwoli ci to zadzwonić, foobar-modenawet jeśli foobarpakiet nie został jeszcze załadowany. Ten sposób foobarnie zostanie załadowany, dopóki nie zadzwoniszfoobar-mode

  • Nie uruchamiaj, package-refresh-contentsjeśli nie musisz instalować pakietów podczas uruchamiania. Jeśli twój init jest skonfigurowany do automatycznej instalacji brakujących pakietów, zastanów się nad ustawieniem arg wiersza poleceń, aby określić, kiedy powinna nastąpić automatyczna instalacja.

  • Jak wyżej, nie rób nic związanego z siecią.
  • Nie ładuj swojego desktopinit, chyba że naprawdę chcesz.

Robić

  • Użyj czegoś takiego, use-packageaby zarządzać swoimi pakietami. Ułatwia to określenie, czego wymagać, co załadować później, co automatycznie ładuje i co ułatwia profilowanie Twojego init na podstawie pakietu.

  • Poznaj różnicę między ładowaniem motywu a włączaniem go. Krótko mówiąc, możesz załadować tyle, ile chcesz, ale upewnij się, że nie włączasz więcej niż jednego. Najlepiej załaduj i włącz tylko jeden motyw. load-themepotrzebuje opcjonalnego argumentu, aby zapobiec włączeniu motywu. Przypadkowe włączenie wielu motywów, które jest powolne i brzydkie podczas uruchamiania, może być łatwe.

  • Oszukiwać: Często są duże globalne tryby, które chcesz załadować przy inicjowaniu, takie jak cofanie drzewa, autouzupełnianie, tryb ido itp. Upewnij się, że funkcje wejścia mają konfigurację autoloadowania, a następnie uruchom bezczynniki czasowe w init, aby załadować pakiety . Robię to undo-tree-mode, idoi inni, i nigdy nie zauważam opóźnienia, ponieważ do czasu, gdy faktycznie muszę ich użyć, są już załadowane.

    Aktualizacja: pakiet use nieco się zmienił, przeczytaj oficjalny plik Readme przed rozpoczęciem korzystania z funkcji timera.

    Na przykład: jeśli chcesz nieco opóźnić ładowanie, global-undo-tree-modemożesz umieścić to w swoim init:

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

    Teraz twój init może kontynuować szczęśliwie i global-undo-tree-modenie zostanie aktywowany, dopóki wszystko inne nie będzie gotowe i nie będziesz za kierownicą.

    use-packageobsługuje wbudowane tego typu zachowanie za pomocą słowa kluczowego: idle. Oto undo-treekonfiguracja z mojego .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)
    
  • Zrób profil swojego init, zawsze zaskakujące jest, gdzie są prawdziwe spowolnienia. profile-dotemacs.el jest niesamowitym narzędziem, którego użyłem, aby pomóc mi obniżyć mój init z ~ 6 sekund do <1 sekundy.

Dobrze skonfigurowany use-packageinit może być niezwykle szybki. Nie kompiluję bajtowo mojego init, który używa use-packagedo skonfigurowania 95 pakietów i uruchamia się w <1 sekundę.

Jordon Biondo
źródło
7
„Zrób profil swojego inicjatora, zawsze zaskakuje, gdzie są prawdziwe spowolnienia”. Ostrzeżenie spoilera, to ta (require 'org)linia. :-)
Malabarba
@Jordanie, czy mógłbyś trochę przedyskutować sposób, w jaki upewniasz się, że funkcje wprowadzania mają skonfigurowane automatyczne ładowanie, a następnie uruchamiasz bezczynne liczniki w swoim init, aby załadować pakiety, w szczególności w trybie cofania drzewa? Dzięki.
Francisco Dibar
@FranciscoDibar Zaktualizowałem mój post o przykłady.
Jordon Biondo
2
Natychmiast używam trybu ido, Cx Cf lub Mx dla smex jest pierwszą rzeczą, którą prawie zawsze robię, kiedy otwieram emacsa i nigdy nie zauważyłem problemu. Także jeśli chcesz cofnąć coś w ciągu sekundy od otwarcia emacsa ... Cóż, nie mam nic do powiedzenia na ten temat. Jeśli tak naprawdę się tym przejmujesz, wypróbuj to sam lub po prostu skorzystaj z nieużywanego timera lub po inicjalizacji.
Jordon Biondo
1
Przydatna jest sugestia licznika czasu bezczynności. Nieco krótsza składnia ładowania to (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 polecenie # ''.
Andrew Swann
8

Coś, co ostatnio pojawiło się na emacs reddit : zmniejsz liczbę wywołań odśmiecania, umieszczając to na początku pliku 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))

W powyższym przykładzie GC jest wywoływane co ~ 50 MB (zamiast domyślnie ~ 800kb), co wydaje się sensowne w nowoczesnym systemie z dużą ilością pamięci RAM.

ffevotte
źródło
1
Tyle że wartość jest (a) prawdopodobnie znacznie wyższa niż potrzebujesz (nie widzę różnicy z jedną dziesiątą tego); oraz (b) ewidentnie nie jest to wartość, którą chcesz zachować poza uruchomieniem, ponieważ duży próg GC równa się dłuższym opóźnieniom za każdym razem, gdy nastąpi GC. Jeśli ustawisz go na wysoki dla init, ustaw go ponownie z powrotem na dół po init. Myślę, że emacs-startup-hookto dobre miejsce do zrobienia tego.
phils
1
@phils Thanks! (a) W mojej konfiguracji 50 Mb daje minimalną liczbę GC (i minimalny czas uruchamiania). Jeśli zejdę tak nisko, jak 10 Mb, różnica jest zauważalna / mierzalna (chociaż w praktyce niewiele się zmienia ...) (b) dobry pomysł, dzięki. Zredagowałem post, aby odzwierciedlić twój komentarz.
ffevotte
6

Czas spędzony na optymalizacji czasu uruchamiania będzie prawdopodobnie dłuższy niż cały dodatkowy czas, który w innym przypadku czekałby na uruchomienie Emacsa.

W tej chwili requirewykonuję 25 wywołań w moim pliku init, aby Flycheck mógł znaleźć błędy ortograficzne w moim kodzie. Mój czas uruchamiania to ...

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

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

Ponadto, w moim systemie, time emacs -Q --eval '(save-buffers-kill-terminal)'ma realod 0m0.404s. Teoretycznie maksymalny czas, jaki mogę zaoszczędzić, to 2,3 sekundy.

Powiedz, że spędzam godzinę na optymalizacji całego pliku init. (Nie liczę dodatkowych 15-30 minut spędzonych w późniejszym terminie, próbując dowiedzieć się, dlaczego moje zmiany nie obowiązywały z powodu skompilowania mojego pliku init.) (Nie liczę też czasu, w którym Flycheck uratowałby mnie w debugerze, gdybym nie usunął requirepołączeń.) Są 3600 sekund na godzinę, więc jeśli uda mi się zaoszczędzić całe 2,3 sekundy, moja inwestycja w czas zwróci się dopiero po 1565 uruchomieniach.

Zakładając, że restartowałem Emacsa 3 razy dziennie, każdego dnia potrzeba półtora roku, aby inwestycja się zwróciła. Gdybym pozostawił tę samą instancję Emacsa działającą przez kilka dni (tak jak często to robię), prawdopodobnie uruchomiłbym tylko 2-5 razy w tygodniu, w którym to przypadku zwrot inwestycji trwałby od 6 do 15 lat.

Jestem hojny, ponieważ prawdopodobnie spędzisz ponad godzinę optymalizując swój start i prawdopodobnie nie zaoszczędzisz maksymalnej teoretycznej liczby sekund.

Jackson
źródło
12
Ale potencjalnie będziesz szczęśliwszy.
phils
2
To może być prawda dla jednej osoby, ale cały sens StackExchange dotyczy udostępniania. Co powiesz na sztuczkę, której znalezienie zajmuje jedna minuta, ale skraca o 1 sekundę czas uruchamiania dziesiątek osób? Czy nadal uważałbyś to za złą inwestycję?
ffevotte
@phils Jak na ironię, zastanawiałem się nad powiedzeniem tego samego, ale na poparcie mojego własnego punktu widzenia! „Zanim zaczniesz narzekać na czas uruchamiania, pomyśl sam:„ Cieszę się, że nie marnowałem czasu na optymalizację tego! ”
Jackson,
@Francesco A ten post to moja sztuczka, która oszczędza dziesiątki osób.
Jackson
@Jackson Nadal nie zgadzam się z tobą w tej konkretnej sprawie, ale przynajmniej teraz rozumiem twój punkt widzenia. Dzięki :)
ffevotte