Подтвердить что ты не робот

Как уменьшить размер выходного кода на C32-шаблоне?

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

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

Обновить (подробности)

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

Ура!

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

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