Как стать автором
Обновить

Комментарии 43

Немногие помнят, как при загрузке приложения с кассеты можно было пойти покушать.
Ну, фотошоп и некоторые другие тяжёлые приложения и до сих пор так грузятся :)
Это конечно перебор, на современных компьютерах даже с HDD успеваешь только чайник включить :)
Пока я не поставил SSD, вполне успевал съесть бутерброд или два, пока загрузятся ОС и приложения в автозагрузке.
Выходит, SSD полезны для здоровья? :)
Наоборот — приложения стартуют за секунду, на еду не остаётся времени, и от нерегулярного питания можно заработать гастрит.
Время на еду должно оставаться независимо от скорости работы компьютера. А вот бутерброды есть в ожидании загрузки — точно не оно. Поэтому SSD полезны. Just my 2 cents.
НЛО прилетело и опубликовало эту надпись здесь
Вроде в прессе о таких случаях не пишут почти никогда. Правда, из этого можно другой вывод сделать — что реально быстрых машин мало в народе. :)
Цифры интересные, но несколько не понятно, какой будет результат на разных проектах. Уж точно не те же проценты от объема бинарников. Думаю, будет полезно показать код, который оптимизировался в ходе работа на статьей.
Кода в работе было много. Приведенные цифры — среднее, и конечно, в конкретных случаях будут другие результаты. Однако, порядок и знак, скорее всего, сохранятся. Можно взять конкретное приложение и поработать над ним, рассмотрев его особенности. Думаю, хватит на отдельную статью.
С месяц назад пытался выжать из своего мини-приложения самый маленький размер. При включенной опции "-О2" выжал 3.5kb, при "-О1" — 3kb. Все опции из статьи использованы. + Ещё склеивал секции .text и .rdata с помощью скрипта линковщика. Но компилятор от Visual Studio тот же код скомпилировал в 2.5kb. Очень обидно, что с помощью любимого компилятора не удалось достичь тех же результатов
Попробуйте подрезать «лишние» секции. Например:
strip FILENAME -R .comment
Из секций и так остались только .text и .idata. Их в одну слить не получилось
SECTIONS { .text ALIGN(16): { *(.text) *(.rdata) *(SORT(.rdata$*)) } }
.text у кого меньше?
попробовать -Os; -fjump-tables и -fno-jump-tables; -fif-conversion -fif-conversion2;
в зависимости от версии GCC можно попробовать поработать с планировщиком и распределителем регистров.
У EXEшника от Visual Studio только одна секция — .data.
Манипуляции с jump-tables и if-conversion не помогли.
GCC у меня 4.7.1:
Скрытый текст
c:\Program Files (x86)\CodeBlocks\MinGW\bin>gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c:/program files (x86)/codeblocks/mingw/bin/../libexec/gcc/mingw32/4.7.1/lto-wra
pper.exe
Target: mingw32
Configured with: ../../src/gcc-4.7.1/configure --build=mingw32 --enable-languages=c,c++,ada,fortran,
objc,obj-c++ --enable-threads=win32 --enable-libgomp --enable-lto --enable-fully-dynamic-string --en
able-libstdcxx-debug --enable-version-specific-runtime-libs --with-gnu-ld --disable-nls --disable-wi
n32-registry --disable-symvers --disable-build-poststage1-with-cxx --disable-werror --prefix=/mingw3
2tdm --with-local-prefix=/mingw32tdm --enable-cxx-flags='-fno-function-sections -fno-data-sections'
--with-pkgversion=tdm-1 --enable-sjlj-exceptions --with-bugurl=http://tdm-gcc.tdragon.net/bugs
Thread model: win32
gcc version 4.7.1 (tdm-1)
К сожалению, нет под рукой GCC под Windows. Подскажите опции при которых секция .text была минимальна (принимая в расчет только оптимизации самого .text). Посмотрю в каком месте GCC можно подкрутить.
Лучший случай:
Скрытый текст
-s -O1 -Os

-nodefaultlibs
-nostartfiles
-mconsole
-lkernel32
-luser32
-lgcc
-Wl,ld_script_merge_rdata_and_text.x

.text
Physical Address 2024 $7E8 %11111101000
Virtual Address 4096 $1000 %1000000000000
Size of Raw Data 2048 $800 %100000000000
Pointer To Raw Data 512 $200 %1000000000
Pointer To Relocations 0 $0 %0
Pointer To Linenumbers 0 $0 %0
Number Of Relocations 0 $0 %0
Number Of Linenumbers 0 $0 %0
Characteristics 1613758560 $60300060 %1100000001100000000000001100000
Если добавить следующие опции, то размер секции .text не меняется.
Скрытый текст
-ffunction-sections -Wl,--gc-sections
-fno-asynchronous-unwind-tables -Wl,--strip-all
-fvisibility=hidden -fvisibility-inlines-hidden
-fno-jump-tables
-fif-conversion2
-fno-asynchronous-unwind-tables
Если -O1 заменить на -O3, то получим:
Скрытый текст
.text
Physical Address 2196 $894 %100010010100
Virtual Address 4096 $1000 %1000000000000
Size of Raw Data 2560 $A00 %101000000000
Pointer To Raw Data 512 $200 %1000000000
Pointer To Relocations 0 $0 %0
Pointer To Linenumbers 0 $0 %0
Number Of Relocations 0 $0 %0
Number Of Linenumbers 0 $0 %0
Characteristics 1613758560 $60300060 %1100000001100000000000001100000
Если убрать скрипт линкера, то секция .text вообще не появляется
Crinkler ужал разницу до 0.23kb: 1.14kb studio vs. 1.37kb GCC. Но сам факт пока остался тем же — догнать студию пока не получилось…
Демосцена 4k? :)
Демосцена — тру! Надеюсь, когда-нибудь смогу поучаствовать. А сейчас так, тренируюсь. Вопрос заинтересовал в принципиальном плане, вот и ковырялся
Ну если ориентироваться только на винду и маленькие файлы, то почему бы не попробовать кринклер? www.crinkler.net/
Спасибо за наводку! Стандартный линковщик студии выдал EXE-файл размером 2.5kb, Crinkler на объектных файлах студии — 1.1kb. Позже попробую прикрутить его к GCC
GCC + Crinkler — полёт нормальный. ЕХЕ 1.37kb, т.е. всего на 0.2kb больше, чем у студии. С таким готов мириться. Спасибо огромное!
Если ещё кому-нибудь нужно: при настройке очень помог Makefile.
Иногда возможные оптимизации скрываются там, где их не ждешь.
GCC по умолчанию делает все функции экспортируемыми из динамической библиотеки. Недавно получилось уменьшить размер библиотеки на 24% (с 16.6 до 12.6 Mb) за счет опций "-fvisibility=hidden -fvisibility-inlines-hidden"
FYI: Есть люди, которые ради развлечени пытаются в ограниченное число байт впихнуть по-максимуму. Например, 64K Intro. Правда там совсем другими способами сжимается код :)
64к? Ну, батенька, вы загнули. Этот монстр не поместится у меня в оперативке, максимум — 4к.
В статье обозначен вывод, что польза от "-flto", с точки зрения размера кода, в основном засчет удаления неиспользуемых функций. То есть можно воспользоваться "-ffunction-sections -Wl,--gc-sections".
"-Os -flto" редкое сочетание, может оказаться и не надежным.
Прежде всего, котаны, надо писать хороший код — не злоупотреблять шаблонами в крестах и т.п.
Далее, выигрыш от конкретных опций gcc зависит от приложения, стиля кода, модной в этом сезоне версии gcc и фазы луны. Поэтому надо брать GC Masher, который автоматически грубой силой переберет все возможные параметры gcc с целью нахождения глобального минимума.
Ну и напоследок можно попробовать сжать бинарник каким-нибудь exe-пакером, типа UPX, или вовсе на коленке соорудить gzip-дроппинг.
В этом месте можно убедиться, что все предыдущие оптимизации размера сказываются на размере сжатого файла не монотонно, и, господи, зачем вообще я пишу этот комментарий.
«хороший код» реально писать, если пишешь его в одиночку и с нуля. Зачастую некоторые интерфейсы уже написаны.
Грубая сила предполагает высокую скорость компиляции или наличие крутого сервера.
Что-то мне подсказывает, что 90% эффекта от «грубой силы» можно добиться «здравым смыслом».
Про архивацию — правда, но уже не про GCC/LD.
На неконтролируемом входном коде можно вообще схватить подчеркнутое той или иной опцией неопределенное поведение в стандарте языка.
Да, здравый смысл конечно 90% покрывает, а грубая сила нужна только для случаев «о боже, я вылез на 35 байт за пределы дозволенного!», да и вообще предполагает прежде всего крохотулечные проекты, потому что никаких серверов не хватит хромиум перебирать.
Кстати, -mfpmath=sse не круто с точки зрения размера — там водятся толстенные 7-байтные инструкции, тогда как олдовые fpu'шные укладываются в 2.
Зато по скорости исполнения выигрывают. Это тоже немаловажный фактор.
Это так, но выбор между размером и скоростью зависит от задачи. В той же сцене интра может грузиться хоть минуту, но самое главное — влезть в ограничение по размеру.
Кстати, -mfpmath=sse не круто с точки зрения размера

Согласен. Особенно если использовать встроеный sin, например. Правда, и вещественная арифметика почти не представлена в тех приложения, что были использованны для получения цифр (для мобилных приложений более свойственны целочисленные вычисления, вещественные завернуты в библиотеки).
С sin вообще забавно получается — если не выпендриваться, gcc на место sin (когда я в последний раз смотрел году в 2009) вместо того, чтобы православно заинлайнить fsin, генерирует вызов в libm, который там у себя внутри считает синус самостоятельно (емнип, оно даже в этот самый fsin не упирается в итоге, но не буду утверждать).
Дело в требуемой точности. У библиотечного и встроенного sin она разная. Насколько я знаю текущий вариант в libm точнее встроенного.
Код написан. Старался писать так, чтоб результирующий файл имел минимальный размер. GCC генерирует результирующий код размером 3kb, Visual Studio — 2.5kb (подробности выше). Стандартный набор опций GC Masher'a уменьшить размер не помог — всё так же 3kb. По-моему, цель данной статьи скорее помочь найти нужные ключи GCC, которые помогут уменьшить размер… И да, при таком размере UPX не ужал ни на байт.
Для такой мелочи и win32-специфики лучше вообще использовать crinkler, но он не понимает объектники, генерируемые gcc (по крайней мере года четыре назад не понимал).
Впрочем, как вы правильно заметили, мы отдаляемся от темы этой статьи.
Спасибо за наводку. Всё прекрасно работает с GCC, подробнее отписал выше
О, это хорошо. Спасибо за информацию — попробую в следующих своих интрах использовать gcc, а то замучался уже с абы какой поддержкой чистых сей студийным компилятором.
Очень интересно, ждем про x86_64!
Да особых отличий не должно быть. Будут те же опции и выводы. Ну разве что "-x32" потенциально добавится для экономии памяти и регистров. Только для x86_64 размеры намного реже критичны.
Размер важен для демосцены, там — да, наслаждаешься безумством «упертых»
Скорость важна для технологических применений (встраиваемые решения, рендеринг и т.п.)
Гораздо важнее КАЧЕСТВО кода. Вымораживает, когда современный софт срыгивает чем-нибудь вроде:
«не могу открыть файл.»
КАКОЙ, блджад, файл ты не можешь открыть, чудо ты корпоративное! Неужели трудно в исходниках прописать конкретно ошибку, сэкономив персоналу ЧАСЫ времени на поиски неисправности…
Зарегистрируйтесь на Хабре, чтобы оставить комментарий