У меня огромная проблема. У меня есть общая библиотека, которая используется во всем моем проекте. Эта библиотека интенсивно использует boost.spirit
а также boost.fusion
, К сожалению, библиотека ок. 700Mb в размере. Все boost.spirit
Тяжелый код используется, и он работает хорошо. Какие шаги можно сделать, чтобы уменьшить его размер? Есть ли инструмент, который может помочь определить, какие экземпляры шаблона тратят большую часть пространства?
Сначала я решил переместить весь дух-ориентированный код в файлы cpp. Во-вторых, я попробую разные флаги компилятора для оптимизации по размеру. Я не знаю, что еще делать.
Обновление (подробнее)
Я использую инструментарий GNU. Огромная библиотека на самом деле является статической библиотекой. Исполняемый файл, который использует эту библиотеку размером 700 МБ, имеет размер 200 МБ. По крайней мере половина кода находится в * .h файлах. Немного boost.spirit
грамматики (очень тяжелые шаблоны) также находятся в файлах * .h.
Ура!
Перемещение сознательного духа кода в .cpp
Файлы — это хороший первый шаг, хотя он может быть неполным, хотя, как вы упоминаете, в заголовочных файлах присутствует грамматика спирта.
Убедитесь, что ни одна из грамматик / правил никогда не экспортируется за пределы библиотеки. Если у вас есть типичный include
/src
каталоги, затем переместите эти файлы (даже если заголовки) в пределах src
каталог.
Отметьте все эти символы как внутренние для библиотеки. Они не должны быть доступны извне библиотеки вообще. Существуют определенные прагмы / атрибуты, зависящие от вашего компилятора, при поиске gcc атрибут видимости: __attribute__ ((visibility ("internal")))
, Это помогает компилятору оптимизировать их соответствующим образом, в частности, компилятор может генерировать код функции, даже если он вставляет его в заданный сайт вызова, на тот случай, если этот адрес функции взят. Однако с внутренней видимостью, поскольку он знает, что код не покинет объект, он может исключить функцию.
Кажется, я помню флаг для объединения идентичных функциональных тел, но не могу найти снова …
--ffunction-sections
поместит каждую функцию в свой сегмент. Сам по себе бесполезен, но компоновщик может удалять неиспользуемые разделы с помощью --gc-sections
, Сейчас без --function-segments
это будет работать только в том случае, если весь исходный файл не будет использован, то есть с безумной детализацией.
Очевидно, вам нужен атрибут видимости, упомянутый Matthieu, иначе все функции в библиотеке «используются» в силу своей видимости.
Это обсуждалось здесь: почему мой выходной исполняемый файл C ++ такой большой?
В основном ищите символы отладки, порядок ссылок, оптимизацию и так далее …
Несколько предложений:
там, где это возможно, попробуйте использовать одни и те же экземпляры шаблона (как простой и надуманный, например, std::vector<int>
а также std::vector<float>
будет иметь одинаковую внутреннюю структуру и может просто обрабатывать данные своих элементов как непрозрачные 4-байтовые двоичные объекты, так что один может делегировать другому, и просто действовать как обертка вещи, которая просто возвращает к правильному типу, так что внутренние вектор должен быть создан только для одного типа, а не для двух.
попробуйте другой компилятор. Некоторые компиляторы используют идентичные экземпляры шаблона, когда это не повлияет на семантику программы, в то время как другие более консервативны.
внимательно следить за тем, что экспортируется из библиотеки. Символы, которые не экспортируются и не имеют внутренних ссылок, могут быть удалены компоновщиком. (Конечно, если вы создаете статическую библиотеку, она не сработает, пока она не будет связана с исполняемым файлом. Чтобы уменьшить размер самой библиотеки, вместо этого вы можете попробовать сделать ее динамической библиотекой)
Но, в конечном счете, похоже, что вам, возможно, придется использовать менее загруженную библиотеку. (или напишите более простой парсер, чем у вас есть сейчас)