Данная статья призвана помочь разработчикам програмного обеспечения, испульзующим GCC компилятор, уменьшить размер кода своих приложений. Все данные в статье получены при помощи x86 GCC компилятора версии 4.7.2 на операционной система Fedora 17 для архитектуры Intel® Atom™.
Довольно существенный выигрыш с точки зрения размера GCC дает динамическая линковка (включенная по умолчанию). То, насколько динамическая линковка выигрывает у стаитической, сильно зависит от используемых библиотек.
Чаще всего, когда речь заходит об оптимизации размера, используется опция “-Os”. Ниже приведена табличка со средними геометрическими размера кода по набору приложений для смартфонов и таблеток.
Результаты в табличке показаны относительно “-Os”. Меньший результат говорит о меньшем размере кода. “-m32, -mfpmath=sse, -march=atom” включены по-умолчанию во всех случаях.
-O2 | 6% |
-O2 -flto | -5% |
-Ofast | 11,5% |
-Ofast -flto | 3% |
-Ofast -funroll-loops | 19% |
-Ofast -funroll-loops -flto | 10,5% |
“-Ofast” (или “-O3”) и “-funroll-loops”, очевидно, увеличивают размер кода. Опция “-flto”, за счет более агрессивной подстановки функций (inline), также должна увеличивать размер кода. Однако, результат противоположный. Почему?
“-flto” делает возможным удаление неиспользуемых функций. Функция может стать таковой, если в конкретной конфигурации приложения она не вызывается или была полностью и во всех местах вызова подставлена в код. Для того, чтобы удалить неиспользуемые функции без “-flto” можно воспользоваться “-ffunction-sections -Wl,—gc-sections”. Данная техника дает хороший результат, если в приложении используются внутренние статические библиотеки.
Приложение все еще слишком большое? Есть еще несколько техник для уменьшения размера. По умолчанию GCC использует опцию “-fasynchronous-unwind-tables”, что увеличивает размер EH (exception handling) секции, даже при компиляции приложений на языке “C”. Это облегчает процесс отладки, однако может существенно увеличить размер кода. Для отключения надо добавить “-fno-asynchronous-unwind-tables” к опциям компиляции.
“-Wl,—strip-all” сообщит линкеру, что надо удалить всю символьную информацию. Это сделает процесс отладки еще сложнее. И все же, если размер кода критичен, опция приемлема.
Ниже приведена табличка отражающая эффект от добавления:
- “-ffunction-sections -Wl,—gc-sections” (+ сборщик мусора)
- “-ffunction-sections -Wl,—gc-sections -fno-asynchronous-unwind-tables” (+ без таблиц раскрутки)
- “-ffunction-sections -Wl,—gc-sections -fno-asynchronous-unwind-tables -Wl,—strip-all” (+ удаление символов)
к различным опциям оптимизации.
Результаты в табличке показаны относительно “-Os”. Меньший результат говорит о меньшем размере кода. “-m32, -mfpmath=sse, -march=atom” включены по-умолчанию во всех случаях.
по умолчанию | + сборщик мусора | + без таблиц раскрутки | + удаление символов | |
-Os | — | -5% | -10,5% | -22,5% |
-O2 | 6% | 0,5% | -3,5% | -13,5% |
-O2 -flto | -5% | -5% | -8% | -17% |
-Ofast | 11,5% | 6% | 2% | —6,5% |
-Ofast -flto | 3% | 2,5% | 0,5% | -6,5% |
-Ofast -funroll-loops | 19% | 12,5% | 9,5% | 3% |
-Ofast -funroll-loops -flto | 10,5% | 10% | 8,5% | 2,5% |
Ниже представлено описание используемых в статье опций компилятора. Полное описание (на английском): gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Optimize-Options.html
- "-Ofast" аналогично "-O3 -ffast-math" включает более высокий уровень оптимизаций и более агрессивные оптимизации для арифметических вычислений (например, вещественную реассоциацию)
- "-flto" межмодульные оптимизации
- "-m32" 32 битный режим
- "-mfpmath=sse" включает использование XMM регистров в вещественной арифметике (вместо вещественного стека в x87 режиме)
- "-funroll-loops" включает развертывание циклов
- "-ffunction-sections" размещает каждую функцию в отдельной секции
- "-Os" оптимизирует производительность и размер
- "-fno-asynchronous-unwind-tables" гарантирует точность таблиц раскрутки только в пределах функции
Ниже представлено описание используемых в статье опций линковщика. Полное описание (на английском): sourceware.org/binutils/docs/ld/Options.html
- “—gc-sections” включает удаление неиспользуемых секций
- “—strip-all” удаляет символьную информацию
ссылка на оригинал статьи http://habrahabr.ru/company/intel/blog/167417/
Добавить комментарий