TL; DR Mam tak dużą liczbę pakietów, że szkodzi to mojemu uruchomieniu. Jeśli nie uważasz, że może tak być, czytaj dalej.
Czas uruchamiania mojego Emacsa jest dość krótki. Nie używam use-package
, po prostu ustawiam mnóstwo haczyków autoload
, aby prawie cały kod został odroczony. W rzeczywistości całość jest ładowana zwykle w mniej niż pół sekundy, mimo że wydaje się to szalonym bałaganem.
Jednak z biegiem czasu zauważyłem, że mój czas uruchamiania dostaje drobiazgowo wolniej, w niewytłumaczalny sposób. W końcu doszło do momentu, w którym czas uruchamiania wynosi ≥ 1 sekundę. W końcu miałem dość i sięgnąłem do sedna problemu. W końcu skomentowałem cały ~/.emacs
plik i stwierdziłem, że czas uruchamiania wciąż wynosił ≥ 1 sekundę. W rzeczywistości ogolił się ~ 0.2
sekund, a czasem nawet krócej. Potem próbowałem emacs -q
i okazało się, że czas uruchamiania wynosił ~ 0.1
sekund.
Po zbadaniu tej sekcji podręcznika Elisp, dowiedziałem się dlaczego emacs -q
został skracając czas uruchamiania tyle. Najwyraźniej emacs -q
powstrzymuje Emacsa przed zrobieniem trzech rzeczy podczas uruchamiania:
- ładowanie pliku init
- ładowanie
default.el
pliku - powołanie
package-initialize
Wykluczyliśmy już mój plik inicjujący, ponieważ skomentowanie mojej całości ~/.emacs
prawie nic nie robi. Nie używam default.el
pliku, więc jest to również wykluczone. Co pozostawia package-initialize
winowajcę za hit.
Dlaczego package-initialize
zabiera tyle czasu na uruchomienie? To było pierwsze pytanie, które sobie zadałem. Czy nie ładuję wszystkiego automatycznie? No tak. Ale to jest właśnie problem.
Znalazłem ten post, który wyjaśnia, że „aktywowanie” pakietów polega na odczytywaniu plików autoload i ustawianiu ścieżek ładowania. To oczywiście powoduje karę we / wy, gdy masz wiele pakietów, ponieważ masz wiele plików autoload do odczytu i wiele ścieżek do ustawienia. Niestety bez tego zadanie zarządzania automatycznymi ładowaniami spada na użytkownika. Innymi słowy, nie pozwalając na package.el
indeksowanie systemu plików w celu automatycznego ładowania plików i ścieżek, musiałbym sam sobie z tym poradzić, co może być żmudnym i podatnym na błędy procesem.
Wolałbym nie iść tą drogą. Obecnie mam 116 pakietów, w tym 107 z ELPA, z czego 25 to zależności. Jestem pewien, że ta ogromna liczba tak bardzo obniża moją wydajność. Ale jestem w rozterce, ponieważ nie chcę usuwać żadnego z moich pakietów.
Czy w takiej sytuacji jest jakiś sposób na odzyskanie czasu uruchamiania błyskawicy?
Aktualizacja:
Rozpoczęliśmy nowy wątek na emacs-devel
liście mailowej o niektórych łatach autorstwa Stefana Monniera (opis tych łatek jest tutaj ), aby rozwiązać ten problem. Każdy może przetestować swoje łatki i wyrazić opinię.
Kolejna aktualizacja:
Wygląda na to, że Stefan Monnier albo nie jest już zainteresowany tym problemem, albo nie otrzymuje moich wiadomości. Jestem skłonny wierzyć w to pierwsze, co jest w porządku, chociaż byłbym wdzięczny za jakąś odpowiedź od niego, jeśli tak jest. Zresztą kod, który do tej pory stworzył dla tego problemu, działa całkiem dobrze. Najnowsze jego łaty można znaleźć tutaj (dla Emacsa 25.3) i tutaj (dla głównej gałęzi Emacsa).Zauważyłem dobre ulepszenia czasu uruchamiania dzięki jego łatkom i jestem w punkcie, w którym czuję się dobrze z czasem uruchamiania, o ile jest on zoptymalizowany tak, jak to możliwe, bez wyłączania funkcji mojego dostosowania. Miałem nadzieję, że te łaty w pewnym momencie znajdą się na linii głównej Emacsa, ale chyba (lub ktoś inny) musiałbym teraz zająć się pochodnią, zamiast Stefana. Mieliśmy trochę uwagi na liście mailingowej dotyczącej przypisywania praw autorskich i licencjonowania. Początkowo nie czułem się z tym dobrze, ale z powodu niektórych komentarzy Richarda Stallmana i innych, przypisanie praw autorskich może nie być tak restrykcyjne, jak początkowo myślałem. Ponadto może być możliwe przekazanie moich dzieł do domeny publicznej jako alternatywa dla przypisania praw autorskich.
W każdym razie dziękuję Stefanowi za dotychczasowe łaty! Mam nadzieję, że nadal będziecie rozwijać te zmiany, ale jeśli nie, to w porządku i mogę je w dalszym ciągu rozwijać. Dziękuję również wszystkim innym, którzy zaoferowali wgląd i wkład w rozwiązanie tego problemu.
Kolejna aktualizacja:
Wow, wygląda na to, że ta funkcja w końcu wylądowała i będzie w Emacs 27. Dzięki Stefan Monnier!
use-package
jest na to sposób.Odpowiedzi:
Jedną z opcji projektowania w pakiecie.el była próba uczynienia rzeczy „prostymi”. Częścią tego jest to, że
package-initialize
wyszukuje wszystkie zainstalowane pakiety, a następnie próbuje dowiedzieć się, które z nich powinny zostać aktywowane (zgodnie z przypinaniem i ponownością wersji w przypadku, gdy dostępnych jest wiele wersji tego samego pakietu), a następnie ładuje każdy<pkg>-autoloads.el
plik pakietu aktywuje .Tak więc dla N zainstalowanych pakietów, oznacza to w zasadzie czytanie N
<pkg>-pkg.el
plików opisu pakietów i N<pkg>-autoloads.el
plików. W przypadku dużych N może to stać się poważnym problemem. Innym potencjalnym problemem związanym z wydajnością jest to, że doda N elementówload-path
, więc za każdym razem, gdyload
Emacs będzie przeszukiwał N katalogów, każdy z nichload
zostanie spowolniony.Istnieją różne sposoby przyspieszenia tego:
Podaj sposób na wstępne obliczenie
~/.emacs.d/elpa/package-initialize.el(c)
pliku, który byłby wynikiem połączenia wszystkich właściwych elementów<pkg>-autoloads.el
we właściwej kolejności. Następniepackage-initialize
może po prostu załadować ten plik, gdy jest obecny i pominąć wszystko inne. Będziesz wtedy potrzebować sposobu na odświeżenie / opróżnieniepackage-initialize.el(c)
pliku, gdy pakiety zostaną dodane / zaktualizowane / usunięte lub gdy zmienisz swójpackage-pinned-packages
lub własnypackage-load-list
. Myślę, że można tego dokonać przy niewielkiej liczbie zmian w systemie (jedyne, co naprawdę wymagałoby zmiany, myślępackage-initialize
, że można powiedzieć, aby „aktywowała się tylko” bez ładowania metadanych o dostępnych pakietach).Zapewnij sposób na budowanie / manipulowanie super-pakietami, tj. Pakiet, który łączy kilka pakietów w jeden (więc jest dodany tylko jeden element
load-path
, jeden<pkg>-pkg.el
i jeden<pkg>-autoloads.el
załadowany). Może to być trudniejsze (ponieważ wtedy nie można aktywować tylko części pakietów zawartych w takich super-pakietach, więc analiza zależności / wersji może być trudna).Pierwsza powyższa opcja powinna być dość łatwa do wdrożenia i
package-initialize
znacznie przyspieszyłaby, gdy zainstalowano wiele pakietów. Jeśli chcesz to wypróbować, możesz poprosić mnie o pomoc.FWIW, właśnie próbowałem zbudować taki plik mega-autoloads „ręcznie” na mojej konfiguracji testowej. Wyniki: podczas gdy
package-initialize
trwa około 0,9 s, ładowaniemega-autoloads.el
pliku zajmuje 0,3 s, co mogę obniżyć do 0,2 s przez powiązanie letload-source-file-function
do zera i do 0,1 s przez kompilację bajtów pliku. Szczerze mówiąc, spodziewałem się lepszego przyspieszenia, ale nadal warto.[EDYCJA] To podejście „mega autoloads” jest teraz dostępne w głównej gałęzi Emacsa (aby stać się Emacs-27 w odległej przyszłości). Jest kontrolowany przez nową
package-quickstart
zmienną.źródło
package.el
programistów. Jaką masz radę, rozpoczynając od pierwszej opcji? Chciałbym zobaczyć, co mogę z tym zrobić, ponieważ wydaje się to o wiele bardziej wykonalne.<pkg>-autoloads.el
plików konfiguruje tylko automatyczne ładowanie i rzeczywiście nie przejmuje się zamawianiem, ale nic nie stoi na przeszkodzie, aby robiły losowe inne rzeczy, a package.el gwarantuje, że pakiet, od którego<pkg>
zależy, zostanie aktywowany przed<pkg>
sobą.Problem,
package-initialize
który opisujesz poświęcając tyle czasu na załadowanie, jest dobrze znanym problemem. Jest to również jeden z problemów, które niektóre frameworki emacsa próbują rozwiązać, ręcznie ładując autoloady.Widzę dwa rozwiązania twojego problemu.
Jednym z głównych powodów rekomendacji emacsa DOOM jest to, że środowisko zarządzania pakietami poza emacsem. Nie interpretuj mnie źle, nadal emacs zajmuje się zarządzaniem pakietami, po prostu zarządzanie pakietami odbywa się poza standardową sesją użytkownika. Oto filozofia: kiedy normalnie uruchamiasz emacsa, powinniśmy być w stanie założyć, że wszystkie pakiety są obecne i można je już załadować. To oszczędza dużo czasu. DOOM emacs zapewnia swego rodzaju odpowiednik
apt-get
lubpacman
emacs. Po zainstalowaniu pakietu, przy każdym uruchomieniu emacsa zakłada się, że jest już zainstalowany; brak pytań.źródło