Как уменьшить размер выходного кода C ++?

У меня огромная проблема. У меня есть общая библиотека, которая используется во всем моем проекте. Эта библиотека интенсивно использует boost.spirit а также boost.fusion, К сожалению, библиотека ок. 700Mb в размере. Все boost.spiritТяжелый код используется, и он работает хорошо. Какие шаги можно сделать, чтобы уменьшить его размер? Есть ли инструмент, который может помочь определить, какие экземпляры шаблона тратят большую часть пространства?

Сначала я решил переместить весь дух-ориентированный код в файлы cpp. Во-вторых, я попробую разные флаги компилятора для оптимизации по размеру. Я не знаю, что еще делать.

Обновление (подробнее)

Я использую инструментарий GNU. Огромная библиотека на самом деле является статической библиотекой. Исполняемый файл, который использует эту библиотеку размером 700 МБ, имеет размер 200 МБ. По крайней мере половина кода находится в * .h файлах. Немного boost.spirit грамматики (очень тяжелые шаблоны) также находятся в файлах * .h.

Ура!

12

Решение

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

  1. Убедитесь, что ни одна из грамматик / правил никогда не экспортируется за пределы библиотеки. Если у вас есть типичный include/src каталоги, затем переместите эти файлы (даже если заголовки) в пределах src каталог.

  2. Отметьте все эти символы как внутренние для библиотеки. Они не должны быть доступны извне библиотеки вообще. Существуют определенные прагмы / атрибуты, зависящие от вашего компилятора, при поиске gcc атрибут видимости: __attribute__ ((visibility ("internal"))), Это помогает компилятору оптимизировать их соответствующим образом, в частности, компилятор может генерировать код функции, даже если он вставляет его в заданный сайт вызова, на тот случай, если этот адрес функции взят. Однако с внутренней видимостью, поскольку он знает, что код не покинет объект, он может исключить функцию.

  3. Кажется, я помню флаг для объединения идентичных функциональных тел, но не могу найти снова …

5

Другие решения

--ffunction-sections поместит каждую функцию в свой сегмент. Сам по себе бесполезен, но компоновщик может удалять неиспользуемые разделы с помощью --gc-sections, Сейчас без --function-segments это будет работать только в том случае, если весь исходный файл не будет использован, то есть с безумной детализацией.

Очевидно, вам нужен атрибут видимости, упомянутый Matthieu, иначе все функции в библиотеке «используются» в силу своей видимости.

4

Это обсуждалось здесь: почему мой выходной исполняемый файл C ++ такой большой?

В основном ищите символы отладки, порядок ссылок, оптимизацию и так далее …

2

Несколько предложений:

  • там, где это возможно, попробуйте использовать одни и те же экземпляры шаблона (как простой и надуманный, например, std::vector<int> а также std::vector<float> будет иметь одинаковую внутреннюю структуру и может просто обрабатывать данные своих элементов как непрозрачные 4-байтовые двоичные объекты, так что один может делегировать другому, и просто действовать как обертка вещи, которая просто возвращает к правильному типу, так что внутренние вектор должен быть создан только для одного типа, а не для двух.

  • попробуйте другой компилятор. Некоторые компиляторы используют идентичные экземпляры шаблона, когда это не повлияет на семантику программы, в то время как другие более консервативны.

  • внимательно следить за тем, что экспортируется из библиотеки. Символы, которые не экспортируются и не имеют внутренних ссылок, могут быть удалены компоновщиком. (Конечно, если вы создаете статическую библиотеку, она не сработает, пока она не будет связана с исполняемым файлом. Чтобы уменьшить размер самой библиотеки, вместо этого вы можете попробовать сделать ее динамической библиотекой)

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

2