概要

Erlang仮想マシン(BEAM)とJavaScriptランタイム上で動作する静的型付け関数型言語Gleamが、10月5日にv1.19.0をリリースした。今回の最大の変更点は、これまでコンパイル時に人間が読めるErlangのソースコードを生成し、それをErlangコンパイラのフロントエンドに渡して処理するという方式を廃止したことだ。開発者のLouis Pilfoldによれば、新しい実装ではGiacomo Cavalieriによる書き直しにより、Erlangコンパイラの中間表現である「Erlang abstract forms」をバイナリエンコード(Erlang external term format)の形で直接出力するようになった。これにより「生成したコードを直接ロードでき、Erlangコンパイラの前半部分をスキップできる」という。

なぜErlangソースコード経由だったのか

Gleamがこれまでテキスト形式のErlangソースコードを経由していた背景には、BEAMバイトコードそのものが安定した仕様ではないという事情がある。Pilfoldは「BEAMバイトコードは固定され不変のものではなく、仮想マシンの新しいリリースごとに進化しうる」と説明しており、バイトコードを直接生成するのはコストに対して利益が小さく、Erlang abstract formsへ出力するアプローチが「コストと利益のスイートスポット」だったと述べている。一方でこの従来方式には弱点があった。ソースコードを経由する過程で行番号などのメタデータが失われやすく、BEAMのクラッシュレポートやスタックトレースに表示される行番号が不正確になることがあった。新方式ではこの問題が解消され、スタックトレースの行番号は常に正確になったという。

パフォーマンスへの影響

100個のモジュールにそれぞれ100個の関数を含むベンチマークプロジェクトでの検証では、v1.17.0と比較してビルド時間が大幅に短縮されたことが示されている。記事中のグラフによれば、ビルド時間はv1.17.0の約430ミリ秒からv1.19.0の約340ミリ秒まで短縮されており、コンパイル経路の簡素化が実際の速度向上に直結していることがわかる。また、JavaScriptへのコンパイル結果にも改善が見られ、パターンマッチの最適化によって、従来は17行に及ぶネストしたif文として出力されていたコードが、最適化後はif/else文全体でも7行程度(条件式自体は1行)に圧縮される例も紹介されている。

その他の変更点と今後の展望

v1.19.0では上記のアーキテクチャ変更に加え、エラーメッセージの充実、TypeScript型定義でのオーバーロード対応、短いリストに対する内部表現の最適化なども行われている。コンパイル経路の簡素化によってコンパイラ自体の保守性が高まったことで、今後はさらなる最適化の余地が広がるとみられる。BEAM上で動く言語としての安定性と、JavaScriptランタイムへの対応を両立させてきたGleamにとって、今回のアーキテクチャ刷新はビルド体験とデバッグ体験の両面を改善する基盤的な変更といえる。