用黄金代替ld-有经验吗?


81

有没有人尝试使用gold代替ld

gold 有望比更快ld,因此它可以帮助加快大型C ++应用程序的测试周期,但是可以用作ld的直接替代品吗?

可以gcc/g++直接呼叫gold。吗?

是否有任何已知的错误或问题?

尽管gold已经有一段时间成为GNU binutils的一部分了,但我在网络上几乎找不到“成功案例”甚至“ Howtos”。

更新:添加了指向黄金的链接和解释它的博客条目

Answers:


53

目前,它正在Ubuntu 10.04上编译更大的项目。在这里,您可以轻松地将其安装并与binutils-gold软件包集成(如果删除该软件包,则会使用旧的ld)。海湾合作委员会将自动使用黄金。

一些经验:

  • 黄金不搜索 /usr/local/lib
  • gold不假定像pthread或rt这样的库,必须手动添加它们
  • 它更快并且需要更少的内存(后者在具有大量增强功能的大型C ++项目中很重要)

什么不起作用:它无法编译内核内容,因此无法编译内核模块。如果Ubuntu更新了fglrx之类的专有驱动程序,它将通过DKMS自动执行此操作。这将失败ld-gold(您必须先删除金牌,然后重新启动DKMS,然后重新安装)ld-gold


谢谢,我想我会尝试一下-在我看来,您提到的限制似乎没有问题。
IanH 2010年

+1:感谢您的分享经验。那性能呢?
神经

9
它的速度要快得多,特别是将巨大的静态库链接到一个二进制文件时,但是我们没有进行任何困难的测量。
诺布

2
@neuro我的测量是将许多对象和.a文件链接到一组约30个.so文件(一个较大,其余很小)和一个可执行的大型商业应用程序的链接。仅测量链接时间和串行运行时间,使用ld的总时间为22.48秒,使用金色的总时间为16.24秒,每次构建的时间为6.24秒。但是,如果我与8个处理器并行运行make,则每次构建的总差异仅为1.42秒。无论进行并行化如何,总体内存使用量均提高了42%。YMMV。
金属

@metal:非常感谢您提供的数据。内存使用情况的改善看起来很棒,ld对此非常贪婪。
神经

40

我花了一些时间来找出如何有选择地使用黄金(即,不是使用符号链接在系统范围内使用),因此将解决方案发布在此处。它基于http://code.google.com/p/chromium/wiki/LinuxFasterBuilds#Linking_using_gold

  1. 创建一个目录,您可以在其中放置金胶脚本。我正在使用~/bin/gold/
  2. 将以下胶粘脚本放在那里并命名~/bin/gold/ld

    #!/bin/bash
    gold "$@"
    

    显然,使其可执行chmod a+x ~/bin/gold/ld

  3. 将您的调用更改gccgcc -B$HOME/bin/gold使gcc在给定目录中查找诸如helper程序之类的调用ld,从而使用胶水脚本而不是system-default ld


1
那是什么操作系统需要的?正如nob在他的回答中所说,对于Ubuntu,只需安装金币binutils-package,编译器将立即使用它。与openSuse相同。
usr1234567 2014年

8
是的,在整个系统范围内替换ld相当容易。我的回答特别针对如何有选择地使用黄金。在这种情况下,我认为任何操作系统都是必需的。
Tilman Vogel

1
@vidstige是的,脚本的优点是它在gold上查找PATH。对于符号链接,您需要指向完整路径。
Tilman Vogel

17

gcc / g ++可以直接调用黄金吗?

只是为了补充答案:有一个gcc选项-fuse-ld=gold(请参阅gcc doc)。尽管AFAIK可以在构建过程中配置gcc,但该选项不会产生任何影响。


5
-fuse-ld=gold不完整。如果必须-Wl,-fuse-ld=gold使用,请在链接时使用。
Nawaz

6
@Nawaz否,-Wl,用于将选项直接传递给ld; 要使用另一个链接器,您需要告诉gcc。请参考文档
calandoa

11

作为Samba开发人员,自几年以来,我几乎一直在Ubuntu,Debian和Fedora上仅使用黄金链接器。我的评估:

  • 黄金比经典链接器快许多倍(感觉:5-10倍)。
  • 最初,存在一些问题,但是大约在Ubuntu 12.04之后就消失了。
  • 黄金链接器甚至在我们的代码中发现了一些依赖问题,因为就某些细节而言,黄金链接器似乎比经典链接器更正确。参见,例如,该Samba commit

我没有选择性地使用过黄金,但是一直使用符号链接或备用机制(如果发行版提供的话)。



5

最低综合基准:LD vs黄金vs LLVM LLD

结果:

  • -Wl,--threads -Wl,--thread-count=$(nproc)对于启用多线程时我尝试过的所有值,黄金的速度大约提高了3到4倍
  • LLD比黄金快2倍!

经过测试:

  • Ubuntu 20.04,GCC 9.3.0,binutils 2.34,sudo apt install lldLLD 10
  • 联想ThinkPad P51笔记本电脑,英特尔酷睿i7-7820HQ CPU(4核/ 8线程),2个三星M471A2K43BB1-CRC RAM(2个16GiB),三星MZVLB512HAJQ-000L7 SSD(3,000 MB / s)。

基准参数的简化描述:

  • 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

# CLI args.

# Each of those files contains n_ints_per_file ints.
n_int_files="${1:-10}"
n_ints_per_file="${2:-10}"

# Each function adds all ints from all files.
# This leads to n_int_files x n_ints_per_file x n_funcs relocations.
n_funcs="${3:-10}"

# Do a debug build, since it is for debug builds that link time matters the most,
# as the user will be recompiling often.
cflags='-ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic'

# Cleanup previous generated files objects.
./clean

# Generate i_*.c, ints.h and int_sum.h
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

# Generate funcs.h and main.c.
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

# Generate *.o
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的调试版本中也观察到了2倍的结果: https

相似的问题: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存档)。

已知的不兼容性



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.