現行のUnixリンカを置き換え可能な最新のリンカであるmoldがバージョン1.0に到達した。LLVM lldリンカのオリジナル作者が開発したmoldは、従来のリンカよりも数倍高速であることを目標としている。
デバッグ-編集-再ビルドのサイクルを大幅にスピードアップすることによって、開発者の生産性向上が可能になる、と開発者のRui Ueyama氏は言う。
具体的に言えば、Chromiumの実行ファイル(サイズ1.8GiB)を1秒以内でリンクできるリンカを使いたいのです。数年前に私が最初に開発した、最高速のオープンソースリンカであるLLVMのlldは、私のマシンでChromiumをリンクするのに12秒程度を要します。つまり目標は、
lld
よりもパフォーマンスを12倍向上させることです。GNUのgoldと比較すれば50倍以上になります。
Ueyama氏の公開したベンチマークによれば、moldはすでに、2GBのChromeを2秒強でリンクすることができている。これはlld
に対して5倍のスピードアップであり、GNU goldより25倍高速なことになる。設定した目標に対してはまだ2倍だが、注目すべき数値であることは間違いない。
ただし、Chromeのベンチマーク結果については有望だが、プログラムによって結果が大きくことなる点にも注意する必要がある。例えばClang 13のコンパイルでは、moldはlld
のわずか2倍高速であるに過ぎない。それでもGNU goldに比較すれば30倍以上速いことになる。
moldは、マルチコアCPUの並列性を積極的に活用することによって、そのパフォーマンスを実現している。Ueyama氏の指摘によれば、既存のリンカは、使用可能なコア数の増加への対処が十分ではないのだ。
ご覧のように、moldは実行中、使用可能なコアをすべて使用することによって、処理を早く終了しています。一方のlldは、存在するコアをほとんど活用できていません。このデモでは、バーの表示がGIFに合うように、並列性を16までに制限しています。
Ueyama氏のベンチマークには、moldがプログラムのリンクに要する時間が、cp
による別の場所へのコピーの2倍程度であることも示されている。これはつまり、設定した目標がcp
に近いパフォーマンスの達成であることを示している。
この目的のためにmoldでは、新たな設計選択を数多く模索している。そのひとつが、入力オブジェクトをディスクから事前にロードしておいて、関連する入力オブジェクトがすべて用意される前に、可能になった時点で処理を行う、というアイデアだ。つまり、リンクには2つのステップがあり、その最初のステップである入力ファイルの推測的解析と前処理においては、すべての入力オブジェクトが用意できている必要はない。この第1ステップを可能な限り早い段階で行っておけば、入力ファイルが段階的に用意されることで、第2ステップをより早く完了することが可能になるのだ。
さらなる高速化は、文字列のインターン化を使用したシンボル解析や文字列セクションのマージなど、計算集中型のタスクを第1ステップで行なうことによって実現されている。
ELFに代わる新たなフォーマットの開発や、inotify
によるオブジェクトファイルの監視といったアプローチも検討したが、Ueyama氏は最終的にそれらを採用しなかった。
目標が1ミリ秒単位の短縮である場合に関連するような、低レベルの詳細なものを含めれば、リンカのパフォーマンスに影響を与えるものは他にもたくさんある。例えば、出力ファイルがディスクに書き込まれた時にリンカプロセスを少しでも早く終了させるようにforkを使用する、といった方法だ。moldの設計資料とともに、Ueyama氏が様々な質問に答えたこちらのHacker Newsのスレッドも、一読に値する興味深いものだ。
moldはまだ開発の初期段階にあるため、バージョンが1.0ではあっても、実用的にlld
を置き換えるレベルには達していない、と作者は述べている。それでも試してみたいということであれば、clang
-fuse-ld
/-ld-path
のコマンド行引数を使えば簡単にできる。gcc
を使用する場合は、-B
フラグを使って独自のld
が見つけられるようにディレクトリを指定する必要がある。