Делает gcc-ссылку на скорость выполнения программы

Я знаю, что порядок привязки в gcc важен для правильного определения символов; но теперь я вижу проблему с быстрым выпуском результирующего исполняемого файла. Я связываю объекты и архивы как

g++ -m32 a.o b.o ar1.a ar2.a -lm -lpthread -lcrypt -lz -pthread -o afast.out

против

g++ -m32 a.o ar1.a b.o ar2.a -lm -lpthread -lcrypt -lz -pthread -o aslow.out

Вторая версия работает в 2 раза медленнее. b.o фактически находится в архивации ar1.a, но ar2.o имеет ссылки на него, поэтому компоновщик жалуется, поэтому мне пришлось поставить b.o. В начале я делал b.o весь путь до конца связи, чтобы сделать правильный порядок зависимостей, хотя затем понял, что он работает даже при начале и даже быстрее.

Кто-нибудь испытал это? Является ли привязка объекта к файлу отличным от порядка архивации? Как может быть какое-либо влияние скорости?

получение аналогичных результатов с gcc3.4.6 или gcc4.1.2

Ответ 1

В зависимости от того, как кладется объектный код в памяти, могут быть значительные различия в скорости выполнения. В общем, вы хотите, чтобы горячие функции были близки друг к другу, поэтому они не смешиваются с холодными функциями, поэтому ваши Icache и TLB не загрязняются холодными функциями. Однако очень маловероятно, что вы пострадали от этого.

Скорее всего, у вас есть некоторые символы, которые разрешены одним способом в "быстром" исполняемом файле, а другой - в "медленном" исполняемом файле. Порядок архивных библиотек и объектных файлов в командной строке имеет значение, и вы можете в конечном итоге вытащить некоторый объект из ar1.a в ссылку "fast", тогда как вы вытащите эквивалентный объект из ar2.a в "медленную" ссылку. Возможно, есть некорректированный код в ar2.a?

Запуск nm -A ar1.a ar2.a и проверка, будут ли какие-либо символы, которые встречаются в обоих, будут первым шагом. Затем вы можете попросить компоновщика создать карту ссылок (с -Wl,-M,map.out) и проверить, откуда эти символы на самом деле появляются в двух ссылках.