GCC уменьшает двоичное раздувание странного побочного эффекта

Странные явления

Я скомпилировал буферы протокола Google без дополнительных параметров для "раздутой" компиляции и скомпилировал с помощью следующей команды ./configure CXXFLAGS="-ffunction-sections -fdata-sections". du-h показывает:

120K ./bloat/bin
124K ./bloat/include/google/protobuf/io
8.0K ./bloat/include/google/protobuf/compiler/java
12K ./bloat/include/google/protobuf/compiler/python
8.0K ./bloat/include/google/protobuf/compiler/cpp
128K ./bloat/include/google/protobuf/compiler
52K ./bloat/include/google/protobuf/stubs
848K ./bloat/include/google/protobuf
852K ./bloat/include/google
856K ./bloat/include
12K ./bloat/lib/pkgconfig
37M ./bloat/lib
38M ./bloat
20K ./unbloat/bin
124K ./unbloat/include/google/protobuf/io
8.0K ./unbloat/include/google/protobuf/compiler/java
12K ./unbloat/include/google/protobuf/compiler/python
8.0K ./unbloat/include/google/protobuf/compiler/cpp
128K ./unbloat/include/google/protobuf/compiler
52K ./unbloat/include/google/protobuf/stubs
848K ./unbloat/include/google/protobuf
852K ./unbloat/include/google
856K ./unbloat/include
12K ./unbloat/lib/pkgconfig
15M ./unbloat/lib
16M ./unbloat
53M .

Детализация:

 ls -gGh bloat/lib/
    total 37M
    -rw-r--r-- 1  13M 2010-09-07 13:57 libprotobuf.a
    -rwxr-xr-x 1  986 2010-09-07 13:57 libprotobuf.la
    -rw-r--r-- 1 1.6M 2010-09-07 13:57 libprotobuf-lite.a
    -rwxr-xr-x 1 1021 2010-09-07 13:57 libprotobuf-lite.la
    lrwxrwxrwx 1   25 2010-09-07 13:57 libprotobuf-lite.so -> libprotobuf-lite.so.6.0.0
    lrwxrwxrwx 1   25 2010-09-07 13:57 libprotobuf-lite.so.6 -> libprotobuf-lite.so.6.0.0
    -rwxr-xr-x 1 771K 2010-09-07 13:57 libprotobuf-lite.so.6.0.0
    lrwxrwxrwx 1   20 2010-09-07 13:57 libprotobuf.so -> libprotobuf.so.6.0.0
    lrwxrwxrwx 1   20 2010-09-07 13:57 libprotobuf.so.6 -> libprotobuf.so.6.0.0
    -rwxr-xr-x 1 5.5M 2010-09-07 13:57 libprotobuf.so.6.0.0
    -rw-r--r-- 1  12M 2010-09-07 13:57 libprotoc.a
    -rwxr-xr-x 1 1.1K 2010-09-07 13:57 libprotoc.la
    lrwxrwxrwx 1   18 2010-09-07 13:57 libprotoc.so -> libprotoc.so.6.0.0
    lrwxrwxrwx 1   18 2010-09-07 13:57 libprotoc.so.6 -> libprotoc.so.6.0.0
    -rwxr-xr-x 1 4.6M 2010-09-07 13:57 libprotoc.so.6.0.0
    drwxr-xr-x 2 4.0K 2010-09-07 13:57 pkgconfig
    ls -gGh unbloat/lib/
    total 15M
    -rw-r--r-- 1 5.8M 2010-09-07 14:03 libprotobuf.a
    -rwxr-xr-x 1  988 2010-09-07 14:03 libprotobuf.la
    -rw-r--r-- 1 764K 2010-09-07 14:03 libprotobuf-lite.a
    -rwxr-xr-x 1 1023 2010-09-07 14:03 libprotobuf-lite.la
    lrwxrwxrwx 1   25 2010-09-07 14:03 libprotobuf-lite.so -> libprotobuf-lite.so.6.0.0
    lrwxrwxrwx 1   25 2010-09-07 14:03 libprotobuf-lite.so.6 -> libprotobuf-lite.so.6.0.0
    -rwxr-xr-x 1 393K 2010-09-07 14:03 libprotobuf-lite.so.6.0.0
    lrwxrwxrwx 1   20 2010-09-07 14:03 libprotobuf.so -> libprotobuf.so.6.0.0
    lrwxrwxrwx 1   20 2010-09-07 14:03 libprotobuf.so.6 -> libprotobuf.so.6.0.0
    -rwxr-xr-x 1 2.7M 2010-09-07 14:03 libprotobuf.so.6.0.0
    -rw-r--r-- 1 3.7M 2010-09-07 14:04 libprotoc.a
    -rwxr-xr-x 1 1.1K 2010-09-07 14:04 libprotoc.la
    lrwxrwxrwx 1   18 2010-09-07 14:04 libprotoc.so -> libprotoc.so.6.0.0
    lrwxrwxrwx 1   18 2010-09-07 14:04 libprotoc.so.6 -> libprotoc.so.6.0.0
    -rwxr-xr-x 1 1.3M 2010-09-07 14:04 libprotoc.so.6.0.0
    drwxr-xr-x 2 4.0K 2010-09-07 14:03 pkgconfig

Вопрос

Я не изменил сценарии сборки для выполнения «--gc-sections» во время компоновки, поэтому не должна ли раздутая сборка быть такой же, если не больше? Чем вызвано уменьшение размеров?

Фон

В данный момент я компилирую низкоуровневую библиотеку с помощью gcc, и эта библиотека представляет собой огромные 2,5 МБ без полос и 970 КБ без полос. Это неприемлемо, и мне нужно удалить мертвый код — я завишу от OpenSSL, протокольных буферов и 3 библиотек от Boost, и я статически свяжу последние 2 со своей библиотекой. Две статически связанные библиотеки должны быть скомпилированы с «-ffunction-sections -fdata-sections», чтобы я мог удалить мертвый код.

Похожий вопрос

Мой следующий вопрос касается того, как указать корень, используемый для устранения мертвого кода.


person Hassan Syed    schedule 07.09.2010    source источник
comment
пришлось удалить старый пост, так как по какой-то причине у меня был двойной пост. Да, 2,5 МБ — это огромно — я написал подобные библиотеки и могу уменьшить их размер до 80–300 КБ (используя MSVC). Цепочка инструментов GCC должна уметь делать то же самое.   -  person Hassan Syed    schedule 07.09.2010
comment
@ Хассан Сайед, я думаю, что ваш фоновый раздел вызывает больше проблем, чем решает. Это не относится к вопросу и звучит так, как будто вы просите способы уменьшить размер двоичного файла. Я бы убрал его или поставил в конце вопроса.   -  person strager    schedule 07.09.2010
comment
Ну, размер в разобранном виде не в счет. Поскольку он содержит все дополнительные материалы, которые вам нужны для устранения ошибок, и не имеет отношения к производству.   -  person Martin York    schedule 07.09.2010
comment
Я бы начал использовать readelf -s и readelf -S (заглавная) для сравнения разделов и символов в этих файлах .so.   -  person Jim Blandy    schedule 09.09.2010
comment
Информационная страница GCC говорит об этих опциях: Когда вы укажете эти опции, ассемблер и компоновщик создадут большие объекты и исполняемые файлы, а также будут работать медленнее.   -  person Jack Lloyd    schedule 14.09.2010
comment
@Hassan Просто интересно, в вашем посте предлагалось уменьшить размер двоичного файла, каков был окончательный результат? Каков был окончательный размер, который вы смогли уменьшить с помощью gcc? Использовались ли для этого какие-либо дополнительные методы?   -  person greatwolf    schedule 25.12.2010


Ответы (2)


Боюсь, усиление не имеет ничего общего с -ffunction-sections -fdata-sections: когда вы указали CXXFLAGS="-ffunction-sections -fdata-sections" в командной строке конфигурации, вы перезаписали флаги по умолчанию, которые были -O2 -g -DNDEBUG. Как следствие, ваш код был скомпилирован без оптимизации.

Вы должны повторить свой тест с CXXFLAGS="-ffunction-sections -fdata-sections -O2 -g -DNDEBUG", и вы получите ожидаемые (т.е. идентичные) результаты.

person Samuel Tardieu    schedule 19.09.2010
comment
Он наверняка не получит идентичных результатов, но ваша теория об отсутствии -O2 несколько правдоподобна. Однако, если он действительно скомпилировал без '-g', то его раздувание должно было быть гораздо меньше, что противоречит наблюдаемым фактам. - person Employed Russian; 19.09.2010
comment
Я проверил свою теорию перед публикацией :) Конечно, результат не будет строго идентичным (поскольку внутри одного и того же объектного модуля вместо вызовов, относящихся к ПК, будут иметь место перекрестные вызовы), но разница в размерах будет очень небольшой. Что касается гораздо меньшей проблемы, не забывайте, что код, скомпилированный с помощью -O0, часто больше, чем код, скомпилированный с помощью -O2, что немного уравновешивает отсутствие -g. - person Samuel Tardieu; 20.09.2010
comment
Это звучит как наиболее вероятная причина, спасибо за объяснение. - person Hassan Syed; 05.10.2010

Компиляция с -ffunction-sections приводит к тому, что каждая функция передается в свой собственный раздел, и это приводит к тому, что каждый объектный файл становится больше (вместо только раздела .text теперь у вас есть .text.foo, .text.bar и т. д.). То же самое для -fdata-sections. Так что результат, который вы получили, именно то, что ожидалось.

Но вас не должно волновать, насколько велика ваша область сборки. Что вас должно заботить, так это размер конечного исполняемого файла (или разделяемой библиотеки).

С указанными вами флагами исполняемый файл «раздутия» может быть больше (но, вероятно, ненамного). Теперь добавьте -Wl,--gc-sections, и ваш "раздутый" исполняемый файл станет заметно меньше.

person Employed Russian    schedule 19.09.2010