Skip to content

Instantly share code, notes, and snippets.

@t-sin
Last active August 10, 2018 07:48
Show Gist options
  • Save t-sin/911d192dac926bf06c2a750083855fc8 to your computer and use it in GitHub Desktop.
Save t-sin/911d192dac926bf06c2a750083855fc8 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

あなたのGNU Emacsはなぜ速いのか

あるいはGNU Emacsのビルド時の特徴

2018-08-10 TANAKA Shinichi

GNU Emacsとは

みんな大好きなテキストエディタ

gnu-emacs.png

GNU Emacsの特徴

  • コアとその他機能が分離されている
    • それにより高い拡張性をもつ
    • ほとんどのエディタ機能がEmacs Lispで書かれているほど
  • 拡張性高すぎてtwitterとかできる😎
    • 画像すら表示できてしまう
  • 全機能のドキュメントを内包している
  • 自由ソフトウェア である
    • GNUの筆頭プロジェクト

そんなGNU Emacs、

  • もちろん使ってるよね…?
  • 激重なんじゃないの…?
  • 「お父さんが使ってます!」

これほどまで多機能で重そうなのに GNU Emacsの起動がなぜ速いのかをお話します

GNU Emacsのソースコード

そのために、まずはGNU Emacsのソースコードを眺めてみる

対象にしたGNU Emacs

バージョン
GNU Emacs 26.1
ソース
https://git.savannah.gnu.org/cgit/emacs.git/snapshot/emacs-26.1.tar.gz

ソースコードの言語比率

GNU Emacsのコア機能はC言語、その他の機能はEmacs Lispで書かれている

コア機能とそれ以外の機能の量を比較すると…

C言語のソースファイル数

~/emacs-26.1$ find . -name '*.c' | wc -l
281

Emacs Lispのインタプリタを含んでいる

Emacs Lispのソースファイル数

~.emacs-26.1$ find . -name '*.el' | wc -l
1764

コアに対してEmacs Lispの数が約6倍

どうやって高速にロードしているのか?

問い. 2000弱あるEmacs Lispを高速にロードする方法とは?

答え.

Emacs Lispファイルは起動時にロードされていない 実行ファイルの中に既にロードされているのだ…

GNU Emacsのビルド過程

  1. Emacs Lispやファイル操作等のコア部分をビルドする
    • 裸のGNU Emacs実行ファイル temacs ができる
  2. できた temacs でコア以外の機能(マウスホイールサポート等)をロードする
    • メモリ上にELispの解釈結果が乗る
  3. メモリに乗ったELisp解釈結果を temacs に書き戻してリンクする
    • 実際に使う実行ファイル emacs ができる
    • こいつには 2. でロードした機能が始めから書き込まれている!

どういうこったい…🤔

黒魔術 unexec 関数

ビルド過程の

  1. メモリに乗ったELisp解釈結果を temacs に書き戻してリンクする

を実行するために用意されている関数

exec は、実行バイナリを読み込んで実行できる形でメモリにロードする

unexec は、実行できる形(マシン語)になったメモリ上のデータを実行バイナリの形で吐き出す

unexec イメージ図

unexec.png

unexec を考慮したビルド

build.png

メモリ上のデータ形式は アーキテクチャにがっちり依存 するので、

unexec の実装はアーキテクチャが増える/変わる毎に作り直す必要がある

_人人人人人人人人人_ > めっちゃつらい <  ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^ ̄

Emacsは衰退しました (2017末)

GNU Linux版 unexecglibc の拡張機能を使って実装されていた

  • malloc の途中状態を読み取る機能
  • ほかには ptex や latex が昔この機能を使っていた

しかし glibc 開発メンバーがその機能を消すことを宣言

その理由は:

  • 10年以上、GNU Emacsしか使っていなかった
  • その機能のせいで最新のメモリ管理技術を取り入れられない

このへんとても参考になる記事

“Emacsは衰退しました - Qiita”, http://archive.fo/WgLkS

ここまでを整理すると

  • GNU Emacsは実行バイナリにロード後のElisp実行状態をぶっこんでいる
  • それは廃止される機能を利用している
  • そして実際に廃止されました

……。

😭😭😭😭

つ い に E m a c s は 死 ぬ の か …

Emacsは死にましぇん!

解決策: Elispの実行状態を アーキテクチャ非依存な形 で吐き出せばよい

Portable dumpper -あるいは地獄の道-

  • とても巨大なGNU Emacsの最下層に手を入れなければならない
  • テスト・品質保証どうするんだ
  • 保存すべきElispインタプリタの状態(グローバル変数)を特定するのは 手作業

でも、無事に取り込まれて GNU Emacsはこうして動いています

ちなみに。

Portable dumperは開発者の中でも賛否両論

  • 「これ入れるんなら開発者止める!!」と言った人も。

10年前に一度京大の人がPortable Dumpoerを提案したら、却下されたらしい

  • 変更がでかすぎて開発者が拒否したんだそうな
論文
“portable dumper: アーキテクチャに依存しない Emacs の起動時間短縮手法”, 永野圭一郎, 林芳樹, 2002,

まとめ

  • GNU Emacsは実行ファイル自体にELispコードを読み込んだ状態なので速い
  • その影には黒魔術的なテクニックが潜んでいる
  • そのおかげで存亡の危機に晒されたこともあった
  • しかしそれをも克服する執念をもっている

つまり…

ほんとのまとめ

E m a c s は 永 遠 に 不 滅 で す ! ! !

(付録1) Emacsについておさらい

Emacsの実装は一つではない!!

  • EMACS
    • TECOエディタのマクロ集
  • EINE / ZWEI
    • LISPマシン用
  • Gosling Emacs
    • 初のUNIX上Emacs
    • ちなみにJavaの開発者のJames Goslingの作
  • GNU Emacs
    • Richard M. Stallmanの作
    • いろんな派生がある
  • XEmacs
    • GNU Emacs 19.xのフォーク
    • 自由ソフトウェアのフォークの初期の例
  • Meadow
    • Windows用で日本語入力ができる
    • GNU Emacsフォーク

(付録2) コア/コアじゃない機能って?

コア機能

コアではない機能

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment