• 作成:

HaskellのGHCによるビルドをLLVMのリンカーLLDで高速化することが出来なかった

リンクが遅い

現在SYAKERAKEをHaskellとYesodで書いています.

ゲーム販売webアプリケーションSYAKERAKEを支える技術, HaskellとYesodで作られています - ncaq

開発上常に問題が発生していて, それはビルドに時間がかかるということです.

コンパイルが必要になる時はまあ仕方がないです. 本質的に時間がかかることに対してはハードウェアの更新で対応するしかないです.

しかし, 差分ビルドが有効になっていても, ちょっとした1つのファイルの変更でかなり時間がかかってしまうという問題が発生しています.

どうもビルドの様子を見ていると, ファイルのコンパイル自体は1つのファイルなのでそんなに時間がかかっていませんが, リンクに時間がかかっているようです.

ここで私は1つの記述を見つけました.

GHC now tries to use the gold and lld linkers by default. These linkers are significantly faster than the BFD linker implementation that most Linux distributions use by default. If gold or lld are not available GHC will use the system's default linker. GHC can be forced to use the default linker by passing --disable-ld-override to configure.

Blog: GHC 8.2.1 is available – GHC

goldやlldがインストールされている場合はそれを使うという文面ですね.

実際リンクに時間がかかる問題が解決したら生産性が向上します. 見つけた時は非常に忙しかったので斧を研いでいる時間が無かったのですが, やっと時間が出来たので, 試してみましょう.

ベンチマーク

現在実際に開発しているリポジトリsyakerakeを利用します. 実際に早くならないと意味がないので.

OSはGentoo/Linux, CPUはAMD Ryzen Threadripper 1950Xです.

テストには for i in $(seq 1 3); do echo ' ' >> src/Application.hs; time stack build --fast; done をスクリプトを使います. 見ての通り数回実行して, 最後の値を採用することにします. 本当は平均を取るべきなのでしょうが, 計算が面倒くさいので最後の値. GHCはtouchしただけでは変更があったと見做さないので, ビルド時間に影響しないであろう空白の値を入力します.

実際の開発環境でビルドが高速されるかが問題なので, クリーンなベンチマーク用の環境ではなく, 実際の開発環境で行います.

しかし, 現在の状況だとwebpackによるビルド時間がかなり長いので, それは無効にしておきます. 実際の開発環境ではyesod develによるビルドを行い, webpackはpoolして個別に動くため, 問題にはなりません. また-O2も無効にしておきます.

比較対象をld.bfdだと思っていたのですが, 調べた結果goldが既に入っているようなので, 既存環境はそちらになりそうですね.

オプションとかでld.bfgを使わせる方法を調べて試してみたのですが, 出来ませんでした. -pgmlオプションと--disable-ld-overrideオプションを試してみたのですがどちらもダメでした. コンパイル時に指定したりするオプションなのでしょうか.

実際重要なのはlldがgoldに比べて高速かどうかなので, ld.bfgとgoldの速度の差はどうでも良いと判断しました.

  • GNU ld (Gentoo 2.30 p1) 2.30.0

  • GNU gold (Gentoo 2.30 p1 2.30.0) 1.15

  • LLD 5.0.1 (compatible with GNU linkers)

  • lld入れる前: stack build --fast 4.54s user 0.81s system 100% cpu 5.298 total

  • lld入れた後: stack build --fast 4.54s user 0.85s system 100% cpu 5.349 total

有意差が無いのですが… 本当にlldが使われている?

lldよりgoldが優先されているのでしょうか. ドキュメントの文章は曖昧でよくわかりません. ソースコードを読みます.

ghcのソースコードを読んだのですが, どうもlldが使われるというのはghc自身のビルドのことなんじゃないだろうかと見え始めました. さらにgccと互換性がないということが書かれているっぽい. 私の環境的にはgoldで我慢する必要があるというようですね.