最小限の合成ベンチマーク:LDvsゴールドvsLLVM LLD
結果:
-Wl,--threads -Wl,--thread-count=$(nproc)
マルチスレッドを有効にするために使用したときに試したすべての値で、ゴールドは約3倍から4倍高速でした
- LLDは金の約2倍速かったです!
テスト済み:
- Ubuntu 20.04、GCC 9.3.0、binutils 2.34、
sudo apt install lld
LLD 10
- Lenovo ThinkPad P51ラップトップ、Intel Core i7-7820HQ CPU(4コア/ 8スレッド)、2x Samsung M471A2K43BB1-CRC RAM(2x 16GiB)、Samsung MZVLB512HAJQ-000L7 SSD(3,000MB /秒)。
ベンチマークパラメータの簡単な説明:
- 1:シンボルを提供するオブジェクトファイルの数
- 2:シンボルプロバイダーオブジェクトファイルあたりのシンボル数
- 3:提供されたすべてのシンボルシンボルを使用したオブジェクトファイルの数
さまざまなベンチマークパラメータの結果:
10000 10 10
nogold: wall=4.35s user=3.45s system=0.88s 876820kB
gold: wall=1.35s user=1.72s system=0.46s 739760kB
lld: wall=0.73s user=1.20s system=0.24s 625208kB
1000 100 10
nogold: wall=5.08s user=4.17s system=0.89s 924040kB
gold: wall=1.57s user=2.18s system=0.54s 922712kB
lld: wall=0.75s user=1.28s system=0.27s 664804kB
100 1000 10
nogold: wall=5.53s user=4.53s system=0.95s 962440kB
gold: wall=1.65s user=2.39s system=0.61s 987148kB
lld: wall=0.75s user=1.30s system=0.25s 704820kB
10000 10 100
nogold: wall=11.45s user=10.14s system=1.28s 1735224kB
gold: wall=4.88s user=8.21s system=0.95s 2180432kB
lld: wall=2.41s user=5.58s system=0.74s 2308672kB
1000 100 100
nogold: wall=13.58s user=12.01s system=1.54s 1767832kB
gold: wall=5.17s user=8.55s system=1.05s 2333432kB
lld: wall=2.79s user=6.01s system=0.85s 2347664kB
100 1000 100
nogold: wall=13.31s user=11.64s system=1.62s 1799664kB
gold: wall=5.22s user=8.62s system=1.03s 2393516kB
lld: wall=3.11s user=6.26s system=0.66s 2386392kB
これは、リンクテストのすべてのオブジェクトを生成するスクリプトです。
生成オブジェクト
#!/usr/bin/env bash
set -eu
n_int_files="${1:-10}"
n_ints_per_file="${2:-10}"
n_funcs="${3:-10}"
cflags='-ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic'
./clean
rm -f ints.h
echo 'return' > int_sum.h
int_file_i=0
while [ "$int_file_i" -lt "$n_int_files" ]; do
int_i=0
int_file="${int_file_i}.c"
rm -f "$int_file"
while [ "$int_i" -lt "$n_ints_per_file" ]; do
echo "${int_file_i} ${int_i}"
int_sym="i_${int_file_i}_${int_i}"
echo "unsigned int ${int_sym} = ${int_file_i};" >> "$int_file"
echo "extern unsigned int ${int_sym};" >> ints.h
echo "${int_sym} +" >> int_sum.h
int_i=$((int_i + 1))
done
int_file_i=$((int_file_i + 1))
done
echo '1;' >> int_sum.h
rm -f funcs.h
cat <<EOF >main.c
#include "funcs.h"
int main(void) {
return
EOF
i=0
while [ "$i" -lt "$n_funcs" ]; do
func_sym="f_${i}"
echo "${func_sym}() +" >> main.c
echo "int ${func_sym}(void);" >> funcs.h
cat <<EOF >"${func_sym}.c"
#include "ints.h"
int ${func_sym}(void) {
#include "int_sum.h"
}
EOF
i=$((i + 1))
done
cat <<EOF >>main.c
1;
}
EOF
ls | grep -E '\.c$' | parallel --halt now,fail=1 -t --will-cite "gcc $cflags -c -o '{.}.o' '{}'"
GitHubアップストリーム。
各Cファイルは非常に大きくなる可能性があるため、オブジェクトファイルの生成は非常に遅くなる可能性があることに注意してください。
タイプの入力が与えられた場合:
./generate-objects [n_int_files [n_ints_per_file [n_funcs]]]
それは生成します:
main.c
#include "funcs.h"
int main(void) {
return f_0() + f_1() + ... + f_<n_funcs>();
}
f_0.c、f_1.c、...、 f_<n_funcs>.c
extern unsigned int i_0_0;
extern unsigned int i_0_1;
...
extern unsigned int i_1_0;
extern unsigned int i_1_1;
...
extern unsigned int i_<n_int_files>_<n_ints_per_file>;
int f_0(void) {
return
i_0_0 +
i_0_1 +
...
i_1_0 +
i_1_1 +
...
i_<n_int_files>_<n_ints_per_file>
}
0.c、1.c、...、 <n_int_files>.c
unsigned int i_0_0 = 0;
unsigned int i_0_1 = 0;
...
unsigned int i_0_<n_ints_per_file> = 0;
これは次のことにつながります:
n_int_files x n_ints_per_file x n_funcs
リンク上の再配置。
それから私は比較しました:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main *.o
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -fuse-ld=gold -Wl,--threads -Wl,--thread-count=`nproc` -o main *.o
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -fuse-ld=lld -o main *.o
テストパラメータを選択するときに緩和しようとしてきたいくつかの制限:
- 100k Cファイルでは、両方のメソッドでmallocが失敗することがあります
- GCCは1Mの追加で関数をコンパイルできません
また、gem5のデバッグビルドで2xを確認しました:https://gem5.googlesource.com/public/gem5/+/fafe4e80b76e93e3d0d05797904c19928587f5b5
同様の質問:https://unix.stackexchange.com/questions/545699/what-is-the-gold-linker
Phoronixベンチマーク
Phoronixは、2017年にいくつかの実際のプロジェクトについてベンチマークを行いましたが、調査したプロジェクトでは、ゴールドの増加はそれほど重要ではありませんでした:https://www.phoronix.com/scan.php?page = article&item = lld4-linux-tests &num = 2(アーカイブ)。
既知の非互換性
LLDベンチマーク
でhttps://lld.llvm.org/彼らはいくつかのよく知られたプロジェクトのビルド時間を与えます。私の合成ベンチマークと同様の結果が得られました。残念ながら、プロジェクト/リンカーのバージョンは提供されていません。彼らの結果では:
- 金はLDより約3倍/ 4倍速かった
- LLDはゴールドよりも3倍/ 4倍速かったので、私の合成ベンチマークよりも大幅に高速化されました
彼らはコメントします:
これは、SSDドライブを備えた2ソケット20コア40スレッドXeon E5-2680 2.80GHzマシンでのリンク時間の比較です。マルチスレッドのサポートの有無にかかわらず、ゴールドとlldを実行しました。マルチスレッドを無効にするために、コマンドラインに-no-threadsを追加しました。
結果は次のようになります。
Program | Size | GNU ld | gold -j1 | gold | lld -j1 | lld
ffmpeg dbg | 92 MiB | 1.72s | 1.16s | 1.01s | 0.60s | 0.35s
mysqld dbg | 154 MiB | 8.50s | 2.96s | 2.68s | 1.06s | 0.68s
clang dbg | 1.67 GiB | 104.03s | 34.18s | 23.49s | 14.82s | 5.28s
chromium dbg | 1.14 GiB | 209.05s | 64.70s | 60.82s | 27.60s | 16.70s