Как отладить (медленный) компоновщик в системе Debian - PullRequest
7 голосов
/ 24 июня 2009

У нас в компании действительно раздражает проблема с нашим компоновщиком (л.д. 2.17). Он работает очень-очень медленно на относительно быстрой системе (Core Duo, 2 ГБ Ram), и я пока не знаю, как это исправить. Компиляция относительно большого проекта занимает от пяти до десяти минут (на соединение с моей системой Gentoo уходит около 5 секунд).

Лично я считаю, что это огромный убийца производительности, по крайней мере для меня. Мы пытались использовать более свежую версию ld (2.19), но безуспешно. Я спросил в #debian о #freenode, но эта проблема, кажется, очень уникальна. Я не нашел никакой информации о подобных проблемах в сети. Это происходит только тогда, когда мы строим с отладочными символами. Я изменил флаги отладочной информации gcc на -g, -g3 и -ggdb, но это тоже не помогло.

Итак, мой вопрос, как вы профилируете и отлаживаете компоновщик? Я никогда не делал ничего подобного, и я не могу найти документацию по этому поводу. В принципе, любой разумный gprof gmon.out был бы очень полезен, так как я мог бы спросить разработчиков binutils о конкретной проблеме. Я просто совершенно не замечаю этого.

Редактировать: Мы "исправили" нашу проблему, переключаясь на debian lenny в большинстве систем. Спасибо за ответы!

Ответы [ 4 ]

6 голосов
/ 25 июня 2009

Вы можете попробовать золото (binutils-gold) вместо ld. Это должно быть быстрее.

Вот цитата из Wikipedia Gold (linker)

Мотивация для написания золота была сделать компоновщик, который быстрее, чем GNU linker [3], особенно для больших приложения, написанные на C ++.

Автор золота (Ian Lance Taylor) опубликовал (длинную) статью о линкерах , где он объясняет свои мотивы при написании золота и почему большинство линкеров работают медленно. Если вам интересна внутренняя работа линкеров, эту статью стоит прочитать.

5 голосов
/ 24 июня 2009

Если вы наблюдаете замедление работы gcc (в отличие от прямого запуска компоновщика как ld), попробуйте скомпилировать с

$ gcc -save-temps -v [... rest of your command line ...]

Это распечатает все промежуточные команды, такие как внутренние collect2 и конечные ld, а также гарантирует, что объекты, переданные этим командам, останутся на диске даже после завершения команды.

Тогда вы сможете запускать команды по отдельности, чтобы найти наихудший этап, а затем запускать его с различными параметрами или профилированием.

Например,

$ echo 'int main() {}' > test.c
$ gcc -save-temps -v test.c
Using built-in specs.
Target: x86_64-pc-linux-gnu
Configured with: /var/tmp/paludis/sys-devel-gcc-4.3.3-r2/work/gcc-4.3.3/configure --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/4.3.3 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.3 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.3/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/4.3.3/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include/g++-v4 --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --disable-altivec --disable-fixed-point --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --enable-multilib --enable-libmudflap --disable-libssp --enable-libgomp --enable-cld --disable-libgcj --enable-objc-gc --enable-languages=c,c++,objc,obj-c++,treelang,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.3.3-r2 p1.1, pie-10.1.5'
Thread model: posix
gcc version 4.3.3 (Gentoo 4.3.3-r2 p1.1, pie-10.1.5)
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic'
 /usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/cc1 -E -quiet -v test.c -D_FORTIFY_SOURCE=2 -mtune=generic -fpch-preprocess -o test.i
ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/include"
#include "..." search starts here:
#include  search starts here:
 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include
 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/include-fixed
 /usr/include
End of search list.
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic'
 /usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/cc1 -fpreprocessed test.i -quiet -dumpbase test.c -mtune=generic -auxbase test -version -o test.s
GNU C (Gentoo 4.3.3-r2 p1.1, pie-10.1.5) version 4.3.3 (x86_64-pc-linux-gnu)
        compiled by GNU C version 4.3.3, GMP version 4.2.4, MPFR version 2.4.1-p5.
warning: GMP header version 4.2.4 differs from library version 4.3.1.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 20f3dbffbfd03e5311a257ae1239cd71
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic'
 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/bin/as -V -Qy -o test.o test.s
GNU assembler version 2.19.1 (x86_64-pc-linux-gnu) using BFD version (GNU Binutils) 2.19.1
COMPILER_PATH=/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/libexec/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/libexec/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64-pc-linux-gnu/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/bin/
LIBRARY_PATH=/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib/:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-save-temps' '-v' '-mtune=generic'
 /usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../.. test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crtn.o
$ ls
a.out  test.c  test.i  test.o  test.s
$ /usr/libexec/gcc/x86_64-pc-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../.. test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crtn.o
$ .../collect2 -v ...
collect2 version 4.3.3 (x86-64 Linux/ELF)
/usr/bin/ld -v --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crti.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../x86_64-pc-linux-gnu/lib -L/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../.. test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-pc-linux-gnu/4.3.3/../../../../lib64/crtn.o
GNU ld (GNU Binutils) 2.19.1
$ 

Если вам нужна помощь в создании отладочной версии ld, вот быстрый рецепт, который поможет вам.

$ sudo apt-get install build-essential dpkg-dev
$ sudo apt-get build-dep binutils
$ apt-get source binutils
$ cd binutils-*
$ DEB_BUILD_OPTIONS='debug noopt nostrip' dpkg-buildpackage -uc -us
$ cd ..
$ sudo dpkg -i *.deb

Однако вместо этого быстрого взлома я бы рекомендовал использовать schroot или sbuild , чтобы избежать загрязнения вашей собственной системы.

3 голосов
/ 25 июня 2009

ответить на вопрос профилирования; вы должны взглянуть на OProfile - это профилировщик системного уровня, который может профилировать несколько запущенных процессов. Это должно позволить вам определить, какой подпроцесс ссылки занимает больше всего времени, и, кроме того, покажет, на какие функции тратится больше всего времени.

1 голос
/ 29 июня 2009

Я хотел бы предложить два способа проверки:

  1. используйте strace, чтобы проверить, какой компоновщик файлов загружает / разбирает ссылку; при этом вы можете знать, что компоновщик ищет ненужный путь.
  2. используйте ld с опцией -verbose, чтобы узнать, что делает ld. Пять минут по сравнению с пятью не должны быть проблемой компоновщика, это должна быть проблема вашего хост-компьютера или какой-то другой вариант.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...