web-dev-qa-db-fra.com

Remplacer ld par de l'or - une expérience?

Quelqu'un a-t-il essayé d'utiliser gold au lieu de ld?

goldpromet d'être beaucoup plus rapide que ld, donc cela peut aider à accélérer les cycles de test pour les grandes applications C++, mais peut-il être utilisé comme remplacement de remplacement pour ld?

gcc/g++ appeler directement gold.?

Y a-t-il des bogues ou des problèmes connus?

Bien que gold fasse partie des binutils GNU depuis un certain temps, je n'ai trouvé quasiment aucune "success story" ni même "Howtos" sur le Web.

( Mise à jour: ajout de liens vers l'or et entrée de blog l'expliquant )

77
IanH

Pour le moment, il compile de plus gros projets sur Ubuntu 10.04. Ici, vous pouvez l'installer et l'intégrer facilement avec le binutils-gold package (si vous supprimez ce package, vous obtenez votre ancien ld). Gcc utilisera alors automatiquement l'or.

Quelques expériences:

  • l'or ne recherche pas dans /usr/local/lib
  • l'or ne suppose pas les bibliothèques comme pthread ou rt, a dû les ajouter à la main
  • il est plus rapide et nécessite moins de mémoire (ce dernier est important sur les grands projets C++ avec beaucoup de boost, etc.)

Ce qui ne fonctionne pas: il ne peut pas compiler de trucs de noyau et donc pas de modules de noyau. Ubuntu le fait automatiquement via DKMS s'il met à jour des pilotes propriétaires comme fglrx. Cela échoue avec ld-gold (vous devez supprimer gold, redémarrer DKMS, réinstaller ld-gold.

49
nob

Comme il m'a fallu un peu de temps pour savoir comment utiliser sélectivement l'or (c'est-à-dire pas à l'échelle du système en utilisant un lien symbolique), je publierai la solution ici. Il est basé sur http://code.google.com/p/chromium/wiki/LinuxFasterBuilds#Linking_using_gold .

  1. Faites un répertoire où vous pouvez mettre un script de colle d'or. J'utilise ~/bin/gold/.
  2. Mettez le script de collage suivant et nommez-le ~/bin/gold/ld:

    #!/bin/bash
    gold "$@"
    

    Évidemment, rendez-le exécutable, chmod a+x ~/bin/gold/ld.

  3. Modifiez vos appels en gcc en gcc -B$HOME/bin/gold, ce qui permet à gcc de rechercher dans le répertoire donné des programmes d'assistance comme ld et utilise donc le script glue au lieu du système par défaut ld.

38
Tilman Vogel

Gcc/g ++ peut-il appeler directement l'or.?

Juste pour compléter les réponses: il y a une option gcc -Fuse-ld=gold (voir doc gcc ). Cependant, AFAIK, il est possible de configurer gcc pendant la construction de manière à ce que l'option n'ait aucun effet.

12
user2273896

En tant que développeur Samba, j'utilise le lieur d'or presque exclusivement sur Ubuntu, Debian et Fedora depuis plusieurs années maintenant. Mon appréciation:

  • l'or est plusieurs fois (ressenti: 5-10 fois) plus rapide que l'éditeur de liens classique.
  • Au départ, il y avait quelques problèmes, mais ils ont disparu depuis environ Ubuntu 12.04.
  • Le lieur d'or a même trouvé des problèmes de dépendance dans notre code, car il semble être plus correct que le classique en ce qui concerne certains détails. Voir, par exemple ce commit Samba .

Je n'ai pas utilisé l'or de manière sélective, mais j'ai utilisé des liens symboliques ou le mécanisme alternatif si la distribution le fournit.

9
Michael Adam

Vous pouvez lier ld à gold (dans un répertoire binaire local si ld est installé pour éviter l'écrasement):

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

ou

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

Certains projets semblent incompatibles avec l'or, en raison de certaines différences incompatibles entre le ld et l'or. Exemple: OpenFOAM, voir http://www.openfoam.org/mantisbt/view.php?id=685 .

3
Kenneth Hoste

Repère synthétique minimal

Résultat: l'or était environ 2x à 3x plus rapide pour toutes les valeurs que j'ai essayées.

générer-objets

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

Étant donné une entrée de type:

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

Cela génère un principal qui fait:

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

où chaque fonction est définie dans un f_n.c fichier et ajoute n_int_file_is fois n_ints_per_file entrées externes:

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

Cela mène à:

n_int_file_is x n_ints_per_file x n_funcs

délocalisations sur le lien.

J'ai ensuite comparé:

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

pour divers triplets d'entrée, ce qui a donné:

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

Quelques limites que j'ai essayé d'atténuer:

  • à 100k fichiers C, les deux méthodes obtiennent occasionnellement des mallocs défaillants
  • GCC ne peut pas compiler une fonction avec des ajouts 1M

Testé sur Ubuntu 18.10, GCC 8.2.0, ordinateur portable Lenovo ThinkPad P51, processeur Intel Core i7-7820HQ (4 cœurs/8 threads), 2x Samsung M471A2K43BB1-CRC RAM (2x 16GiB), Samsung SSD MZVLB512HAJQ-000L7 (3 000 Mo/s).

J'ai également observé un 2x dans la version de débogage de gem5: https://gem5.googlesource.com/public/gem5/+/fafe4e80b76e93e3d0d05797904c19928587f5b5

DragonFlyBSD est passé à l'or comme éditeur de liens par défaut. Il semble donc être prêt pour une variété d'outils.
Plus de détails: http://phoronix.com/scan.php?page=news_item&px=DragonFlyBSD-Gold-Linker

2
usr1234567