wake-up-neo.com

Ld durch gold ersetzen - irgendwelche erfahrungen?

Hat jemand versucht, gold anstelle von ld zu verwenden?

goldverspricht viel schneller als ld zu sein, daher kann es helfen, die Testzyklen für große C++ - Anwendungen zu beschleunigen, kann aber als Ersatz für verwendet werden ld?

Kann gcc/g++ direkt gold aufrufen.?

Gibt es bekannte Fehler oder Probleme?

Obwohl gold seit einiger Zeit Teil der GNU binutils ist, habe ich im Web fast keine "Erfolgsgeschichten" oder gar "Howtos" gefunden.

( Update: Links zu Gold und Blog-Eintrag hinzugefügt, um es zu erklären )

77
IanH

Momentan werden größere Projekte auf Ubuntu 10.04 kompiliert. Hier können Sie es einfach mit dem Paket binutils-gold Installieren und integrieren (wenn Sie dieses Paket entfernen, erhalten Sie Ihr altes ld). Gcc verwendet dann automatisch Gold.

Einige Erfahrungen:

  • gold sucht nicht in /usr/local/lib
  • gold nimmt keine libs wie pthread oder rt an, musste sie per hand hinzufügen
  • es ist schneller und benötigt weniger Speicher (der spätere ist wichtig für große C++ - Projekte mit viel Boost usw.)

Was nicht funktioniert: Es kann kein Kernel-Material und daher keine Kernel-Module kompilieren. Ubuntu macht dies automatisch über DKMS, wenn proprietäre Treiber wie fglrx aktualisiert werden. Dies schlägt mit ld-gold Fehl (Sie müssen Gold entfernen, DKMS neu starten, ld-gold Neu installieren).

49
nob

Da ich eine Weile gebraucht habe, um herauszufinden, wie man Gold selektiv verwendet (d. H. Nicht systemweit mithilfe eines Symlinks), werde ich die Lösung hier veröffentlichen. Es basiert auf http://code.google.com/p/chromium/wiki/LinuxFasterBuilds#Linking_using_gold .

  1. Erstellen Sie ein Verzeichnis, in das Sie ein Goldkleber-Skript einfügen können. Ich benutze ~/bin/gold/.
  2. Gib das folgende Klebeskript ein und nenne es ~/bin/gold/ld:

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

    Machen Sie es natürlich ausführbar, chmod a+x ~/bin/gold/ld.

  3. Ändern Sie Ihre Anrufe in gcc in gcc -B$HOME/bin/gold, wodurch gcc im angegebenen Verzeichnis nach Hilfsprogrammen wie ld sucht und daher das Glue-Skript anstelle des System-Standards ld verwendet.

38
Tilman Vogel

Kann gcc/g ++ direkt Gold aufrufen?

Nur um die Antworten zu ergänzen: es gibt eine gcc-Option -Fuse-ld=gold (siehe gcc doc ). AFAIK, es ist jedoch möglich, gcc während des Builds so zu konfigurieren, dass die Option keine Auswirkungen hat.

12
user2273896

Als Samba-Entwickler benutze ich den Gold-Linker seit einigen Jahren fast ausschließlich auf Ubuntu, Debian und Fedora. Meine Einschätzung:

  • gold ist um ein Vielfaches (Filz: 5-10-fach) schneller als der klassische Linker.
  • Anfangs gab es ein paar Probleme, die aber seit Ubuntu 12.04 in etwa verschwunden sind.
  • Der Gold-Linker hat sogar einige Abhängigkeitsprobleme in unserem Code festgestellt, da er in einigen Details korrekter zu sein scheint als der klassische. Siehe z. dieses Samba-Commit .

Ich habe Gold nicht selektiv verwendet, sondern Symlinks oder den alternativen Mechanismus verwendet, sofern die Distribution dies vorsieht.

9
Michael Adam

Sie können ld mit gold verknüpfen (in einem lokalen Binärverzeichnis, wenn Sie ld installiert haben, um ein Überschreiben zu vermeiden):

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

oder

ln -s `which gold` /usr/local/bin/ld
8
Delan Azabani

Einige Projekte scheinen mit Gold nicht kompatibel zu sein, da es einige inkompatible Unterschiede zwischen ld und Gold gibt. Beispiel: OpenFOAM, siehe http://www.openfoam.org/mantisbt/view.php?id=685 .

3
Kenneth Hoste

Minimaler synthetischer Benchmark

Ergebnis: Gold war bei allen Werten, die ich ausprobiert habe, etwa 2x bis 3x schneller.

objekte erzeugen

#!/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 .

Bei einer Eingabe vom Typ:

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

Dies erzeugt eine Hauptleitung, die Folgendes bewirkt:

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

wobei jede Funktion in einer separaten f_n.c - Datei definiert ist und n_int_file_is mal n_ints_per_file externe Ints hinzufügt:

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

Dies führt zu:

n_int_file_is x n_ints_per_file x n_funcs

mzüge auf dem Link.

Dann habe ich verglichen:

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

für verschiedene Eingangsdrillinge, die ergaben:

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

Einige Grenzen habe ich versucht zu mildern:

  • bei Dateien mit 100 KB erhalten beide Methoden gelegentlich fehlgeschlagene Mallocs
  • GCC kann keine Funktion mit 1M-Zusätzen kompilieren

Getestet auf Ubuntu 18.10, GCC 8.2.0, Lenovo ThinkPad P51, Intel Core i7-7820HQ-CPU (4 Kerne/8 Threads), 2x Samsung M471A2K43BB1-CRC RAM (2x 16GiB), Samsung MZVLB512HAJQ-000L7 SSD (3.000 MB/s).

Ich habe auch ein 2x im Debugbuild von gem5 beobachtet: https://gem5.googlesource.com/public/gem5/+/fafe4e80b76e93e3d0d05797904c19928587f5b5

DragonFlyBSD hat als Standardlinker auf Gold umgestellt. Es scheint also für eine Vielzahl von Werkzeugen bereit zu sein.
Weitere Details: http://phoronix.com/scan.php?page=news_item&px=DragonFlyBSD-Gold-Linker

2
usr1234567