Подтвердить что ты не робот

Замена ld на золото - любой опыт?

Кто-нибудь пытался использовать gold вместо ld?

gold promises будет намного быстрее, чем ld, поэтому это может ускорить цикл тестирования для больших приложений на С++, но может ли он использоваться в качестве замены для замены ld?

Может gcc/g++ напрямую вызвать gold.?

Есть ли какие-либо ошибки или проблемы?

Хотя gold является частью GNU binutils с тех пор, я почти не нашел "историй успеха" или даже "Howtos" в Интернете.

(Обновление: добавлены ссылки на золото и запись в блоге, объясняющие его)

4b9b3361

Ответ 1

В настоящий момент он компилирует большие проекты на Ubuntu 10.04. Здесь вы можете легко установить и интегрировать его с пакетом binutils-gold (если вы удалите этот пакет, вы получите старый ld). Gcc автоматически будет использовать золото.

Некоторые события:

  • золото не ищет в /usr/local/lib
  • золото не предполагает, что libs, такие как pthread или rt, должен был добавить их вручную
  • он быстрее и требует меньше памяти (более поздняя важна для больших проектов на С++ с большим увеличением и т.д.).

Что не работает: он не может скомпилировать файлы ядра и, следовательно, модули ядра. Ubuntu делает это автоматически через DKMS, если он обновляет проприетарные драйверы, такие как fglrx. Это не удается с помощью ld-gold (вам нужно удалить золото, перезапустить DKMS, переустановить ld-gold.

Ответ 2

Как мне потребовалось некоторое время, чтобы узнать, как выборочно использовать золото (т.е. не общесистемно использовать символическую ссылку), я отправлю решение здесь. Он основан на http://code.google.com/p/chromium/wiki/LinuxFasterBuilds#Linking_using_gold.

  • Создайте каталог, в который вы можете поместить золотой клей script. Я использую ~/bin/gold/.
  • Поместите следующий клей script и назовите его ~/bin/gold/ld:

    #!/bin/bash
    gold "[email protected]"
    

    Очевидно, сделайте его выполнимым, chmod a+x ~/bin/gold/ld.

  • Измените свои вызовы на gcc на gcc -B$HOME/bin/gold, что делает gcc в данном каталоге для вспомогательных программ, таких как ld, и, следовательно, использует клей script вместо системного по умолчанию ld.

Ответ 3

Может ли gcc/g++ напрямую называть золото?

Просто для дополнения ответов: есть опция gcc -fuse-ld=gold (см. Gcc doc). Хотя, AFAIK, можно настроить gcc во время сборки таким образом, чтобы эта опция не имела никакого эффекта.

Ответ 4

Как разработчик Samba, я использую золотой компоновщик почти исключительно в Ubuntu, Debian и Fedora уже несколько лет. Моя оценка:

  • золото во много раз (чувствуется: в 5-10 раз) быстрее, чем классический линкер.
  • Первоначально было несколько проблем, но они пошли примерно с Ubuntu 12.04.
  • Золотой компоновщик даже обнаружил некоторые проблемы с зависимостями в нашем коде, поскольку он кажется более правильным, чем классический, в отношении некоторых деталей. Смотрите, например, этот коммит самбы.

Я не использовал золото выборочно, но использовал символические ссылки или механизм альтернатив, если дистрибутив предоставляет его.

Ответ 5

Вы можете связать ld с gold (в локальном двоичном каталоге, если у вас установлен ld, чтобы избежать перезаписи):

ln -s `which gold` ~/bin/ld

или

ln -s `which gold` /usr/local/bin/ld

Ответ 6

Минимальный синтетический бенчмарк

Результат: золото было примерно в 2–3 раза быстрее для всех значений, которые я пробовал.

генерировать объекты-

#!/usr/bin/env bash
set -eu

# CLI args.

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

# Each function adds all ints from all files.
# This leads to n_int_file_is 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_file_is" ]; 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 upstream.

Учитывая ввод типа:

./generate-objects [n_int_file_is [n_ints_per_file [n_funcs]]]

Это генерирует главное, что делает:

return f_0() + f_1() + ... + f_(n_funcs)()

где каждая функция определена в отдельном файле f_n.c и добавляет n_int_file_is раз n_ints_per_file внешних целых:

int f_0() { return i_0_0 + i_0_1 + ... + i_(n_int_file_is)_(n_ints_per_file); }

Это приводит к:

n_int_file_is 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 -o main *.o

для различных входных триплетов, которые дали:

10000 10 10
nogold: wall=3.70s user=2.93s system=0.75s max_mem=556356kB
gold:   wall=1.43s user=1.15s system=0.28s max_mem=703060kB

1000 100 10
nogold: wall=1.23s user=1.07s system=0.16s max_mem=188152kB
gold:   wall=0.60s user=0.52s system=0.07s max_mem=279108kB

100 1000 10
nogold: wall=0.96s user=0.87s system=0.08s max_mem=149636kB
gold:   wall=0.53s user=0.47s system=0.05s max_mem=231596kB

10000 10 100
nogold: wall=11.63s user=10.31s system=1.25s max_mem=1411264kB
gold:   wall=6.31s user=5.77s system=0.53s max_mem=2146992kB

1000 100 100
nogold: wall=7.19s user=6.56s system=0.60s max_mem=1058432kB
gold:   wall=4.15s user=3.81s system=0.34s max_mem=1697796kB

100 1000 100
nogold: wall=6.15s user=5.58s system=0.57s max_mem=1031372kB
gold:   wall=4.06s user=3.76s system=0.29s max_mem=1652548kB

Некоторые ограничения, которые я пытался смягчить:

  • при файлах 100k C оба метода время от времени получают неудачные mallocs
  • GCC не может скомпилировать функцию с добавлением 1M

Протестировано на Ubuntu 18.10, GCC 8.2.0, ноутбуке Lenovo ThinkPad P51, процессоре Intel Core i7-7820HQ (4 ядра /8 потоков), 2x оперативной памяти Samsung M471A2K43BB1-CRC (2x 16 ГБ), Samsung MZVLB512HAJQ-000L7 SSD (3000 МБ/с)).

Я также наблюдал 2x в отладочной сборке gem5: https://gem5.googlesource.com/public/gem5/+/fafe4e80b76e93e3d0d05797904c19928587f5b5

Подобный вопрос: https://unix.stackexchange.com/questions/545699/what-is-the-gold-linker

Тесты фороникса

В 2017 году Phoronix провел несколько сравнительных тестов для некоторых реальных проектов, но для проектов, которые они исследовали, прирост золота был не столь значительным: https://www.phoronix.com/scan.php?page=article&item=lld4-linux-tests&num=2 (архив).

Ответ 7

Некоторые проекты кажутся несовместимыми с золотом из-за некоторых несовместимых различий между ld и gold. Пример: OpenFOAM, см. http://www.openfoam.org/mantisbt/view.php?id=685.

Ответ 8

DragonFlyBSD переключился на золото в качестве своего компоновщика по умолчанию. Таким образом, он, кажется, готов для различных инструментов.
Подробнее: http://phoronix.com/scan.php?page=news_item&px=DragonFlyBSD-Gold-Linker