Sourcery CodeBench - гигантомания или норма? :)
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 13.05.15 04:46
Оценка: +1
Решил сваять мелкую утилитку для маршрутизатора, поставил Sourcery CodeBench Lite for MIPS, от конца 2014. Из того, что размер инсталлятора — 620 метров, ожидал, что оно развернется гига в полтора-два максимум. Оно развернулось в шесть гигов и 84 тысячи файлов. От такой широты я малость офигел и полез по дереву смотреть, что и где. 90% всего объема занимает mips-linux-gnu/libc. Для чего там такие дикие объемы?

Ладно, собрал простейший "Hello, world", который в статической сборке получился аж в 700 кб, что тоже весьма удивило. Ну да, отладочная информация — добавил -g0, но размер не уменьшился. Убрал отладочные символы strip'ом — осталось 500 кб. Это действительно минимально необходимый объем кода, требуемого для вывода одной строки на консоль, или я чего-то не понимаю?

И это версия Lite — боюсь даже предположить, сколько будет занимать полная.
Re: Sourcery CodeBench - гигантомания или норма? :)
От: Zhendos  
Дата: 13.05.15 15:29
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

EM> Это действительно минимально необходимый объем кода, требуемого для вывода одной строки на консоль, или я чего-то не понимаю?


Можно использовать "-fdata-sections -ffunction-sections" при компиляции
и "-Wl,--gc-sections" при линковки, тогда не используемые функции будут удалены,
но возможно для этого нужно пересобраться libc с этими ("-fdata-sections -ffunction-sections")
опциями
Re[2]: Sourcery CodeBench - гигантомания или норма? :)
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 14.05.15 07:59
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Можно использовать "-fdata-sections -ffunction-sections" при компиляции

Z>и "-Wl,--gc-sections" при линковки, тогда не используемые функции будут удалены,

После добавления всех перечисленных ключей размер исполняемого файла уменьшился с 700 до 650 кб, а после отрезания символов — до 550. Откуда там берется столько кода на элементарные операции? Причем замена printf на puts никакого влияния на размер не оказывает.

Кстати, что нужно сказать gcc, чтобы он изначально не добавлял символы к файлу? -g0 не помогает.
Re[3]: Sourcery CodeBench - гигантомания или норма? :)
От: Zhendos  
Дата: 15.05.15 16:02
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, Zhendos, Вы писали:


Z>>Можно использовать "-fdata-sections -ffunction-sections" при компиляции

Z>>и "-Wl,--gc-sections" при линковки, тогда не используемые функции будут удалены,

ЕМ>После добавления всех перечисленных ключей размер исполняемого файла уменьшился с 700 до 650 кб, а после отрезания символов — до 550. Откуда там берется столько кода на элементарные операции? Причем замена printf на puts никакого влияния на размер не оказывает.


Потому что библиотека не собрана с "-fdata-sections -ffunction-sections",
и поэтому если puts вызывает какой-то хелпер из другого объектного файла,
то подтянется весь "другой" объектный файл с хелпером, и так по цепочке.

Вы можете посмотреть все это вручную, взять libc.a, или как там он называется,
вызвать
ar x libc.a
, извлечь кучу объектных файлов,
и линковаться последовательно, типа

grep fputs *.o


прилинковываем нужные .o файлы, потом снова на что-нибудь ругается и т.д.

На вскидку, fputs внутри использует какой-нибудь мьютекс внутри, в файле мьютексом может
быть какое-нибудь логирование ошибок, оно тянет printf, они malloc и пошло поехало,
пересоберите glibc с "-fdata-sections -ffunction-sections", думаю половину можно будет выкинуть.

ЕМ>Кстати, что нужно сказать gcc, чтобы он изначально не добавлял символы к файлу? -g0 не помогает.


Можно при линковке передать линкеру опцию --strip-all, как с "--gc-sections": "-Wl,--strip-all".
Re[4]: Sourcery CodeBench - гигантомания или норма? :)
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 15.05.15 16:20
Оценка:
Здравствуйте, Zhendos, Вы писали:

Z>Потому что библиотека не собрана с "-fdata-sections -ffunction-sections",

Z>и поэтому если puts вызывает какой-то хелпер из другого объектного файла,
Z>то подтянется весь "другой" объектный файл с хелпером, и так по цепочке.

Однако... То есть, в библиотеке все функции сложены в одну секцию, и линкер умеет цеплять только секцию целиком?

В "поганой винде" (а также в досе) еще с незапамятных времен считалось крайне дурным тоном класть более одной крупной функции в одну секцию, а компиляторы/линкеры, цепляющие функции независимо от их расположения в секциях, появились как бы не пятнадцать лет назад.

Z>Вы можете посмотреть все это вручную, взять libc.a, или как там он называется,

Z>вызвать
ar x libc.a
, извлечь кучу объектных файлов,

Z>и линковаться последовательно

А просто посмотреть, как функции разложены по секциям, можно?

Z>На вскидку, fputs внутри использует какой-нибудь мьютекс внутри, в файле мьютексом может

Z>быть какое-нибудь логирование ошибок, оно тянет printf, они malloc и пошло поехало,

Да это-то понятно. Оно ж везде так, однако в той же винде программа из единственного printf, полностью статически собранная компилятором/линкером от MS 2012 года, имеет размер 52 кб, а из puts — 48. То есть, на порядок меньше. Отчего у меня глаза на лоб и полезли.

Z>пересоберите glibc с "-fdata-sections -ffunction-sections", думаю половину можно будет выкинуть.


То есть, такая программа будет примерно в 250 кб? Но это ведь тоже запредельно много. Отчего там код такой неимоверно толстый?
Re[5]: Sourcery CodeBench - гигантомания или норма? :)
От: Zhendos  
Дата: 15.05.15 17:25
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, Zhendos, Вы писали:


Z>>Потому что библиотека не собрана с "-fdata-sections -ffunction-sections",

Z>>и поэтому если puts вызывает какой-то хелпер из другого объектного файла,
Z>>то подтянется весь "другой" объектный файл с хелпером, и так по цепочке.

ЕМ>Однако... То есть, в библиотеке все функции сложены в одну секцию, и линкер умеет цеплять только секцию целиком?


Не совсем, библиотека (статическая) это архив объектных файлов,
и вот в пределах одного файла линкер (GNU ld) цепляет секцию целиком,
а не используемые объектники выкидывает.

Например, файлов в архиве /usr/lib64/libc.a у меня 1553, соотвественно
что-то он точно выкинет.


ЕМ>В "поганой винде" (а также в досе) еще с незапамятных времен считалось крайне дурным тоном класть более одной крупной функции в одну секцию, а компиляторы/линкеры, цепляющие функции независимо от их расположения в секциях, появились как бы не пятнадцать лет назад.


Ну, статическая линковка для Linux, это все-таки довольно редкий подход, все используют ".so",
и наверное поэтому такой оптимизацией никто не заморачивался.

Z>>Вы можете посмотреть все это вручную, взять libc.a, или как там он называется,

Z>>вызвать
ar x libc.a
, извлечь кучу объектных файлов,

Z>>и линковаться последовательно

ЕМ>А просто посмотреть, как функции разложены по секциям, можно?


Да,
objdump -h libc.a


Z>>На вскидку, fputs внутри использует какой-нибудь мьютекс внутри, в файле мьютексом может

Z>>быть какое-нибудь логирование ошибок, оно тянет printf, они malloc и пошло поехало,

ЕМ>Да это-то понятно. Оно ж везде так, однако в той же винде программа из единственного printf, полностью статически собранная компилятором/линкером от MS 2012 года, имеет размер 52 кб, а из puts — 48. То есть, на порядок меньше. Отчего у меня глаза на лоб и полезли.


Ну, с gcc
printf("hello\n");
==
fputs("hello\n", stdout);
,
т.к. в компиляторе есть соотвествующая оптимизация, и все printf без параметров он заменяет на fputs.

Z>>пересоберите glibc с "-fdata-sections -ffunction-sections", думаю половину можно будет выкинуть.


ЕМ>То есть, такая программа будет примерно в 250 кб? Но это ведь тоже запредельно много. Отчего там код такой неимоверно толстый?


"Половину" это оценка с потолка, без пересборки не узнаешь.
И при сборке можно выключить скажем nscd (кэширующий демон DNS) и прочую хрень.
Отредактировано 15.05.2015 17:27 Zhendos . Предыдущая версия .
Re[5]: Sourcery CodeBench - гигантомания или норма? :)
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 15.05.15 19:50
Оценка: :)))
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>В "поганой винде" (а также в досе) еще с незапамятных времен считалось крайне дурным тоном класть более одной крупной функции в одну секцию, а компиляторы/линкеры, цепляющие функции независимо от их расположения в секциях, появились как бы не пятнадцать лет назад.


Это же опенсорс. Берёте код линкера, напильник в зубы — и вперёд, и с песней!
[КУ] оккупировала армия.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.