GCC x86, как уменьшить размер кода

от автора

      Времена, когда программисты пытались выжать максимум из размера своего приложения, безвозвратно ушли. Основной причиной является существенное увеличение объемов оперативной памяти и дискового простраства на современных компьютерах. Немногие помнят, как при загрузке приложения с кассеты можно было пойти покушать. Или как можно было считать моргания дисковода, косвенно определяя размер приложения. Пожалуй, только разработчики програмного обеспечения под встраиваемые системы до сих пор заботятся о размере кода и потребляемой памяти. Могут ли таблетки и смартфоны вернуть разработчиков «назад в будущее»?
      Данная статья призвана помочь разработчикам програмного обеспечения, испульзующим 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *