多くのパッケージにもかかわらず、どうすれば起動時間を改善できますか?


19

TL; DR膨大な量のパッケージがあるため、起動時間が遅くなります。それが事実であると思わない場合は、読み進めてください。


私のEmacsの起動時間は非常に短いです。を使用せず、ほとんどすべてのコードが遅延するように、use-package大量のフックとautoloadsを設定するだけです。現実には、それはクレイジーな混乱のように見えますが、全体が通常0.5秒未満で読み込まれます。

しかし、時間が経つにつれて、起動時間が微妙に遅くなり、不可解になっていることに気付きました。最終的には、起動時間が1秒以上になるまでになりました。私はついに十分になり、問題の根本を掘り下げました。私は最終的に私の全体のコメントアウト~/.emacsファイルを、その起動時間だったまだ ≥1秒。実際、わずか0.2数秒で削り取られ、時にはそれ以下になりました。その後、私は試しemacs -qてみましたが、起動時間は〜0.1秒でした。

Elispマニュアルのこのセクションを調べてみると、emacs -q起動時間を大幅に短縮した理由がわかりました。明らかにemacs -q、起動時にEmacsが3つのことを行うのを停止します。

  1. 初期化ファイルをロードする
  2. default.elファイルをロードする
  3. 呼ぶ package-initialize

私の全体をコメントアウトして~/.emacsもほとんど何も起こらないので、すでに初期化ファイルを除外しています。私はdefault.elファイルを使用しないので、それも除外されます。これがpackage-initializeパフォーマンスヒットの原因となっています。

なぜpackage-initializeそんなに多くのスタートアップ時間を費やしているのでしょうか?それが私が自分に尋ねた最初の質問でした。すべてをオートロードしませんか?はい、そうです。しかし、それはまさに問題です。

ポスト」パッケージは、自動ロードファイルの読み取りとロードパスの設定で構成されることを説明するこの投稿を見つけました。これは、多くのパッケージを持っている場合、読み込むべきオートロードファイルと設定するパスが多いため、明らかにI / Oペナルティが発生します。残念ながら、これがないと、オートロードを管理するタスクはユーザーの手に落ちます。言い換えれば、package.elファイルとパスを自動ロードするためにファイルシステムをクロールさせずに、それを自分で管理する必要があり、それは退屈でエラーが発生しやすいプロセスになる可能性があります。

私はその道を進んで行きたくない。現在116個のパッケージがあり、そのうち107個はELPAからのもので、25個は依存パッケージです。この途方もない数が、私のパフォーマンスをひどく低下させているのだと確信しています。しかし、パッケージを削除したくないので、私は困惑しています。

このような状況で、雷の起動時間を取り戻すための救済策はありますか?


更新:

この問題を解決するために、Stefan Monnierによるいくつかのパッチ(これらのパッチの説明はこちら)について、メーリングリストで新しいスレッドを開始しまし。誰でも彼のパッチをテストしてフィードバックを送ることができます。emacs-devel

別の更新:

Stefan Monnierはこの問題にもう関心がないか、私のメッセージを受け取っていないようです。私は前者を信じる傾向がありますが、それは問題ありませんが、そうであれば彼からのある種の反応に感謝します。とにかく、この問題のために彼がこれまでに作成したコードは非常にうまく機能しています。彼の最新のパッチは、ここ(Emacs 25.3用)およびここ(Emacsマスターブランチ用)にあります。彼のパッチのおかげで起動時間に良い改善が見られ、カスタマイズの機能を削除することなく可能な限り最適化されているので、起動時間に満足しています。これらのパッチがいつかEmacsメインラインに組み込まれることを望んでいましたが、私(または他の誰か)は今はStefanの代わりにトーチを取る必要があると思います。メーリングリストには、著作権の割り当てとライセンスに関するスパーが少しありました。最初はそうしなかったが、リチャード・ストールマンや他の人からのコメントのために、著作権の譲渡は当初考えていたほど制限的ではないかもしれない。さらに、著作権の譲渡に代わるものとして、作品をパブリックドメインにコミットすることも可能かもしれません。

いずれにせよ、これまでのパッチについてStefanに感謝します!これらの変更の開発を続けていただければ幸いですが、そうでない場合は大丈夫であり、いつか開発を続けることができます。また、この問題を解決するための洞察と貢献を提供してくれたすべての人に感謝します。

さらに別の更新:

うわー、この機能がついに登場し、Emacs 27に搭載されるようです。StefanMonnierに感謝します!


いい質問ですね。
ドリュー

use-packageこれに行く方法です。
ドッジー

問題を軽視しようとはしていません(起動待ち時間は重要です!)が、emacsをデーモン/サーバーとして実行することを検討してください。
GManNickG

1
@GManNickGサーバーとしてEmacsを実行しています。残念ながら、時々Emacsを強く押しすぎたり、いじくり回しすぎたりするため、再起動が問題をクリーンアップするための最良の方法です。その場合、起動時間が最適になるようにしています。
GDP2

回答:


13

package.elの設計上の選択の1つは、物事を「シンプル」にしようとすることでした。これの一部は、package-initializeインストールされているすべてのパッケージを検索し、それらのどれがアクティブ化されるべきかを特定しようとすることです(ピン留め、および同じパッケージの複数のバージョンが利用可能な場合のバージョンの新しさによる)。各パッケージの<pkg>-autoloads.elファイルをアクティブにします。

したがって、N個のインストール済みパッケージの場合、基本的にN個の<pkg>-pkg.elパッケージ記述ファイルとN <pkg>-autoloads.elファイルを読み取ることを意味します。大きなNの場合、それは深刻な問題になる可能性があります。別の潜在的なパフォーマンスの問題は、にN個の要素を追加するためload-pathloadEmacsがN個のディレクトリを検索するたびに、それぞれloadが遅くなることです。

これを高速化するためのさまざまな方法があります。

  • ~/.emacs.d/elpa/package-initialize.el(c)すべての権利<pkg>-autoloads.elを正しい順序で連結した結果であるファイルを事前計算する方法を提供します。次に、package-initializeこのファイルが存在するときにロードし、他のすべてをスキップできます。その後package-initialize.el(c)、パッケージが追加/更新/削除されたとき、package-pinned-packagesまたはを変更したときにファイルを更新/フラッシュする何らかの方法が必要になりますpackage-load-list。これは、システムにほとんど変更を加えずに行うことができると思います(実際に変更が必要なのはpackage-initialize、利用可能なパッケージに関するメタデータをロードせずに「有効化のみ」を指示できるようにすることだけです)。

  • スーパーパッケージ、つまり、複数のパッケージを1つに結合するパッケージを構築/操作する方法を提供します(したがってload-path、1つだけの要素が追加され、1 <pkg>-pkg.elつと1つが<pkg>-autoloads.elロードされます)。これは、実行がより困難になる可能性があります(そのようなスーパーパッケージに含まれるパッケージの一部のみをアクティブにできないため、依存関係/バージョン分析が難しい場合があります)。

上記の最初のオプションは実装が非常に簡単で、多くのパッケージがインストールされている場合はpackage-initialize はるかに高速になります。これを試してみたい場合は、お気軽にお問い合わせください。

FWIW、私はテストセットアップでそのようなメガオートロードファイルを「手作業で」構築しようとしました。結果:package-initialize約0.9 mega-autoloads.el秒かかりますが、ファイルの読み込みには0.3秒かかりload-source-file-function、nilにletバインドすることで0.2秒に、ファイルをバイトコンパイルすることで0.1秒にできます。正直に言うと、より高速化することを期待していましたが、それでも価値はあります。

[編集]この「メガ自動ロード」アプローチは、Emacsのmasterブランチで利用可能になりました(遠い将来Emacs-27になる予定です)。新しいpackage-quickstart変数によって制御されます。


これらは非常に興味深いアイデアです。最初のものは、より現実的であり、難易度が低いように聞こえます。2番目のものは非常に興味深いものですが、それはpackage.el開発者の仕事のように思えます。その最初のオプションから始めるにあたって、どのようなアドバイスがありますか?それがはるかに実行可能と思われるので、私はそれで打ち出すことができるものを見たいです。
GDP2

el-getは、単一の自動ロードファイルアプローチを使用し、基本的にほとんどの場合に機能します。自動ロードが評価されるファイルシステム内の場所に依存する一部のパッケージには問題があります。しかし、「正しい順序で」という意味には従いません。それは現在のpackage.elにとっても決定的だったと思いますか?)
npostavs

@Stefanは、可能であれば、ここで解決策を共有してください。
マヌエルUberti

1
@npostavs:ほとんどの<pkg>-autoloads.elファイルは自動ロードのみを設定し、実際には順序を気にしませんが、ランダムな他のことを妨げるものは何もありません。package.elは、<pkg>依存するパッケージがそれ<pkg>自体の前にアクティブ化されることを保証します。
ステファン

1
この問題に関する別のアップデート:私たちは、メーリングリストに新しいトピックを始めました、ここで、誰でも上またはテストステファンの変化コメントアウトして自由です。
GDP2

6

package-initializeロードに時間がかかることについて説明する問題は、よく知られた問題です。また、一部のemacsフレームワークがオートロードを手動でロードして解決しようとする問題の1つでもあります。

あなたの問題に対する2つの解決策があります。

  1. パスを設定し、関心のあるパッケージのオートロードをロードする機能を記述(またはフレームワークから抽出)します。
  2. 速度を明示的に対象とするフレームワークを使用します。個人的にはDOOM emacsをお勧めします。このフレームワークでは、約1秒で200以上のパケットをロードしています。

DOOM emacsを推奨する主な理由の1つは、フレームワークがパッケージ管理をemacsの外部に置くことです。誤解しないでください。パッケージ管理を行っているのはまだemacsであり、パッケージの管理は標準ユーザーセッションの外部で行われているだけです。ここでの哲学は、通常emacsを開始するとき、すべてのパッケージが存在し、すでにロードできると想定できることです。これにより多くの時間を節約できます。DOOM emacsは、emacsに相当する、apt-getまたはpacmanemacsに相当するものを提供します。パッケージがインストールされると、emacsが起動するたびに既にインストールされていると見なされます。質問はありません。


この問題が私だけに影響しているわけではないことを知ってうれしいです。DOOM Emacsを紹介してくれてありがとう。それを詳しく見て、自分の設定に何が適応できるかを確認する必要があります。
GDP2

私はしばらくの間、DOOM emacsで遊んでいます(そして、できる限り貢献しています)。問題がある場合は、お気軽にご連絡ください。
UndeadKernel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.