HN 日本語サマリー

← 一覧へ戻る
プログラミング

Wild対Moldのベンチマーク

Benchmarking Wild vs. Mold (davidlattimore.github.io)

22 pointsby birdculture0 コメント

要約

この記事では、リンカー(リンクエディタ)であるWildとMoldのパフォーマンスベンチマーク結果の差異について調査しています。Moldが最近発表したベンチマーク結果ではWildが遅いと示されましたが、これはWildが以前発表した結果と大きく異なっていました。著者は、ベンチマーク設定(出力ファイルの扱い、ファイルシステム、フォークの有無など)の違いが原因であることを特定し、Moldのベンチマーク結果を再現することに成功しました。また、Moldが最近大幅に高速化していることも示唆されています。

全文翻訳

David Lattimore - 2026-09-18 Moldは最近リンカーのベンチマークを更新し、初めてWildを含めました。これらのベンチマークでは、Wildの直近のリリース(8月4日)で発表されたベンチマークとは対照的に、WildがMoldよりも著しく遅いことが示されています。この記事は、ベンチマーク結果にこれほど大きな違いがある理由を理解しようとする試みです。 Moldのベンチマークは2台のマシンで実行されました。 - 64コア(128スレッド)のThreadripper、Ubuntu 24.04搭載 - Apple M1 Ultra(16パフォーマンスコア)、Asahi Linux搭載 Wildの直近のベンチマークは1台のマシンで実行されました。 - 16コア(32スレッド)のRyzen 9955hx、Ubuntu 26.04搭載 ベンチマーク設定の大きな違いの1つは、出力ファイルに関連しています。私たちのベンチマークは、以前のリンカー実行から存在する出力ファイルを使用して実行されます。Moldのベンチマークは、リンカーの呼び出し間に、出力ファイルを削除します。これはリンカーのパフォーマンスに大きな影響を与える可能性があります。また、その影響はファイルシステムに大きく依存します。 Wildのベンチマークは歴史的にtmpfsで実行されてきました。これは、ベンチマークのノイズを減らし、SSDの摩耗を避けるためでした。今になって考えると、これはおそらく間違いでした。なぜなら、ほとんどのユーザーはtmpfsでビルドを行う可能性は低いからです。Moldのベンチマークは、より妥当な選択肢であるext4を使用しています。今後、両方の組み合わせを使用する可能性があります。 もう一つの違いは、Moldのベンチマークがデフォルトの動作である起動時のフォークをオーバーライドして--no-forkを渡していることです。これはシャットダウンコストを削減するためです。Wildのベンチマークは、時間を測定する際にはこの設定をデフォルトのままにし、メモリ使用量を測定する場合にのみ--no-forkを渡します。 次に、Moldのベンチマーク結果から、私たちが実行するベンチマークのサブセットを以下に示します。 プログラム | Wild (s) | Mold (s) | Wild/Mold ------- | -------- | -------- | -------- blender-debug | 1.81 | 1.56 | 1.2x godot-debug | 0.81 | 0.62 | 1.3x blender-release | 0.20 | 0.25 | 0.8x clang-release | 0.15 | 0.14 | 1.0x そして、こちらが私たちの結果です。 ベンチマーク | Wild (s) | Mold (s) | Wild/Mold ----------- | -------- | -------- | -------- blender-debug | 2.23 | 1.79 | 1.2x godot-debug | 1.11 | 0.89 | 1.2x blender-release | 0.30 | 0.33 | 0.9x clang-release | 0.21 | 0.20 | 1.0x Wild/Moldの比率を1つの表にまとめると、以下のようになります。 プログラム | Moldベンチマーク | このベンチマーク --------- | --------------- | -------------- blender-debug | 1.2x | 1.2x godot-debug | 1.3x | 1.2x blender-release | 0.8x | 0.9x clang-release | 1.0x | 1.0x 異なるCPUアーキテクチャ、異なるキャッシュサイズ、RAMなどを搭載したマシンで実行していることを考えると、結果は予想される限り近いものです。 これで類似の結果を再現できたので、Wildが1ヶ月前に発表したベンチマーク結果とこれほど異なる理由を掘り下げてみましょう。Wildが発表したベンチマークセットに含まれているclang-releaseベンチマークに焦点を当てます。Moldのベンチマークが使用する設定(ext4+delete+no-fork)から始めて、Wildが歴史的に使用してきた設定(tmpfs+no-delete+fork)で終わるまで、いくつかの異なる構成を試します。 ベンチマーク | Wild (s) | Mold (s) | Wild/Mold --------- | -------- | -------- | -------- clang-release.ext4-delete-no-fork | 0.21 | 0.20 | 1.0x clang-release.ext4-no-delete-no-fork | 0.14 | 0.20 | 0.7x clang-release.tmpfs-delete-no-fork | 0.16 | 0.20 | 0.8x clang-release.tmpfs-no-delete-no-fork | 0.14 | 0.19 | 0.7x clang-release.tmpfs-no-delete-fork | 0.11 | 0.19 | 0.6x この記事の残りの部分では、tmpfs+no-delete+forkの設定を使用します。Wildは、少なくともここでベンチマークされたバージョンでは、フォークを許可し、出力が既に存在し、tmpfs上にある場合に最もパフォーマンスを発揮します。つまり、Moldのベンチマークで使用される設定とは逆です。しかし、これは主にWildが非tmpfsファイルシステム上での新しいファイルの作成と書き込みを高速化するOS固有の最適化を欠いているためです。Moldの作者は、論文「mold: A Massively Parallel Linker」でこれらの最適化について説明しています。具体的には、ファイルスペースを事前に割り当てるためにfallocateを使用し、ファイルをマッピングするためにhugepagesを使用しています。これらの2つの変更は既にWildに実装されており、次のリリースに含まれる予定です。 しかし、Wildの8月4日のベンチマークとMoldの8月28日のベンチマークの間には、依然としてかなりのパフォーマンス差があります。何が起きているのかを見るために、過去1年ほどのMoldとWildの各リリースをベンチマークしました。ここではclang-releaseを再度ベンチマークします。このベンチマークでは、Wild 0.6.0が引数ファイルと通常のコマンドライン引数の混在をサポートしていなかったため、私自身のclangのリリースビルドを使用しました。また、空のsframeに遭遇した場合のエラーを回避するために、moldに--discard-section=.sframeを渡しました。これは修正済みですが、修正されていないmoldバージョンでベンチマークを実行したかったのです。実質的に、これは上記のclang-releaseとは別のものではありますが類似したベンチマークと見なされるべきです。 この結果から、Moldは最近著しく高速化していることがわかります。Wildの8月4日のベンチマークは、Moldの2.42.0および2.42.1リリース前に行われました。これらのリリースで主な改善が見られました。 記事の冒頭で、M1 Mac上のMoldのベンチマーク結果に類似した結果をほぼ再現することに成功しました。しかし、Threadripperの結果は再現できていません。私にはそのようなハードウェアがありません。92GiB RAMを搭載した私の16コアRyzen 9955hxは、ローエンドマシンとはかけ離れていますが、384GiB RAMを搭載した64コアThreadripperではありません。私の推測では、上記の違いを超えたこの大きな差は、おそらくWildが128スレッドで実行され、Moldが32スレッドで実行されていることに起因する可能性があります。私の16コア(32スレッド)マシンでは、Wildは24スレッドから32スレッドに移行する際に、パフォーマンスが向上し続けています(下のグラフを参照)。このため、スレッドキャップは導入していません。しかし、これはあくまで推測です。 もしThreadripperを持っていて、異なるスレッド数でWildのベンチマークを試したい方がいれば、教えてください。