Портирую программу на платформу OpenWRT, она получается размером где-то 140Kb.
Мне необходимо уменьшить её хотя бы килобайт на 20-30. Для этого я решил:
а) найти большие функции, оптимизировать их размер.
б) минимизировать зависимости из stdlib и прочего.
Подскажите, как это лучше всего сделать? Т.е.:
а) как получить список самых больших функций, получившихся при компиляции?
б) какие функции тянут из библиотек больше всего зависимостей?
Компилятор: GCC 4.x, процессор: Arm (портирую на роутер ASUS WL-520GU)
P.S.: -Os, -Wl,--gc-sections, strip и т.д. я применял; это реально помогает, но нужно
ещё сильнее уменьшить exe-шник
Re: Оптимизация размера программы: самые большие функции/мод
M>а) как получить список самых больших функций, получившихся при компиляции?
Как вариант. Взять IDA Pro она умеет показывать функции и их размер, в том числе и дизасмить вашу архитектуру. Можно отсортировать и смотреть там.
Ещё наверно можно сгенерить map файл и по нему ориентироваться.
M>б) какие функции тянут из библиотек больше всего зависимостей?
кто ж это вам скажет не зная что у вас там внутри получилось. Сами смотрите.
Re: Оптимизация размера программы: самые большие функции/мод
Здравствуйте, malphunction, Вы писали:
M>Портирую программу на платформу OpenWRT, она получается размером где-то 140Kb. M>Мне необходимо уменьшить её хотя бы килобайт на 20-30. Для этого я решил: M>а) найти большие функции, оптимизировать их размер. M>б) минимизировать зависимости из stdlib и прочего.
Насчет больших функций — согласен.
Насчет зависимостей из stdlib — не совсем понимаю. Что там может быть такого большого?
M>Подскажите, как это лучше всего сделать? Т.е.: M>а) как получить список самых больших функций, получившихся при компиляции?
Map-файл получить тебе уже советовали. Это, конечно, штука хорошая, но разобраться в нем трудновато (и далеко не все в нем есть).
Я в свое время баловался с nm и objdump. В результате выяснилось, что проще всего написать скриптик, который парсит дамп твоего дизассемблированного приложения и считает длину функций по их адресам (как разницу между оффсетом начала функции и начала следующей функции). Objdump надо натравливать, естественно, на непострипанный бинарь.
У этого метода, конечно, недостатки есть: длина включает паддинг, добавленный компилятором, и для последней функции длина остается непосчитанной (хотя можно и ее вычислить косвенными методами, но мне было лениво — там обычно .fini, она короткая).
Единственная проблема — работает ли objdump с бинарями под ARM.
M>P.S.: -Os, -Wl,--gc-sections, strip и т.д. я применял; это реально помогает, но нужно M>ещё сильнее уменьшить exe-шник
Стрипать не обязательно — дебажные символы при старте программы в память не грузятся. Их отладчик грузит, когда под ним запускаешь.
Впрочем, если файл физически в роутер не влазит — тогда да
Бзззззззжжжжж
Re[2]: Оптимизация размера программы: самые большие функции/
Здравствуйте, chemey, Вы писали:
C>Здравствуйте, malphunction, Вы писали:
M>>Портирую программу на платформу OpenWRT, она получается размером где-то 140Kb. M>>Подскажите, как это лучше всего сделать? Т.е.: M>>а) как получить список самых больших функций, получившихся при компиляции?
можно для начала для каждого объектного файла посмотреть размер секции кода с помощью утилиты size из binutils,
а потом уже копать конкретный объектный файл.
C>Единственная проблема — работает ли objdump с бинарями под ARM.
конечно работает, а как бы он по вашему с помощью gcc собрал программу, без binutils?
Re[2]: Оптимизация размера программы: самые большие функции/
Попробую с map-файлами и binutils.
Удивлен, что нет универсального решения, разве народ не занимается оптимизацией собственных программ по размеру?
Для встраиваемых решений это же ещё актуально.
C>Насчет зависимостей из stdlib — не совсем понимаю. Что там может быть такого большого?
Ошибся. Не stdlib, а шаблоны: мне нужны std::vector и std::string.
Тоже не ясно, как считать их размер? И стоит ли их как-то оптимизировать?
Я вот попытался написать свой аналог std::string на функциях strlen, strcat
и т.п. -- выигрыш составил пару процентов, не стоило и браться :(
C>Стрипать не обязательно — дебажные символы при старте программы в память не грузятся. Их отладчик грузит, когда под ним запускаешь. C>Впрочем, если файл физически в роутер не влазит — тогда да :)
Да, мне именно размер исполнимого файла уменьшить, чтобы в роутер его засунуть.
Re[3]: Оптимизация размера программы: самые большие функции/
Здравствуйте, malphunction, Вы писали:
M>Удивлен, что нет универсального решения, разве народ не занимается оптимизацией собственных программ по размеру?
это будет очень муторно. советую глядеть в сторону станд. функций. среди них могут быть очень большие универсальные: scanf, printf, I/O вообще. ещё можно заменить макросы (как getc/putc) на вызовы функций
Люди, я люблю вас! Будьте бдительны!!!
Re: Оптимизация размера программы: самые большие функции/мод
Здравствуйте, malphunction, Вы писали:
M>P.S.: -Os, -Wl,--gc-sections, strip и т.д. я применял; это реально помогает, но нужно M>ещё сильнее уменьшить exe-шник
еще есть такой момент : обычно если тянется функция из .obj, то obj целиком линкуется в ехе (это дефолтное поведение gcc + vs).
в этом случае мы в компании стараемся распилить .cpp на два исходника таким образом, чтобы при линковке потребовался лишь один .obj
поэтому рекомендую вам оценить объем кода, который никогда не используется в ехе и попробовать его убрать из финального .ехе
это несложно сделать, так как у мейнстрим компиляторов есть опции, которые заставляют линкер вычищать мертвый код (время линковки может заметно вырасти)
можно еще coverage посчитать спец. утилитами
успехов
Re[2]: Оптимизация размера программы: самые большие функции/
Здравствуйте, uzhas, Вы писали:
U>еще есть такой момент : обычно если тянется функция из .obj, то obj целиком линкуется в ехе (это дефолтное поведение gcc + vs).
.... U>это несложно сделать, так как у мейнстрим компиляторов есть опции, которые заставляют линкер вычищать мертвый код (время линковки может заметно вырасти)
Так а я сразу компилирую с параметрами: -fdata-sections -ffunction-sections
А потом линкую: -s -Wl,--gc-sections
Вырезает всё мёртвое.
Время компиляции/компоновки замедляется, но прожка небольшая, так что эффект мал.
Re[3]: Оптимизация размера программы: самые большие функции/
Здравствуйте, malphunction, Вы писали:
M>Так а я сразу компилирую с параметрами: -fdata-sections -ffunction-sections M>А потом линкую: -s -Wl,--gc-sections
M>Вырезает всё мёртвое.
M>Время компиляции/компоновки замедляется, но прожка небольшая, так что эффект мал.
Попробуйте добавить
-fno-exceptions -fno-rtti
Должно дать немного выигрыша по размеру.
Вы, кстати, уже попробовали что-то маленькое на C++ запустить на рутере?
Я сталкивался с проблемой, отсуствия libstdc++.so (рантайма) на устройстве, что сводит на нет все попытки написания на C++.
... << RSDN@Home 1.2.0 alpha 4 rev. 1477>>
Re[4]: Оптимизация размера программы: самые большие функции/
Здравствуйте, Sanik, Вы писали:
S>Должно дать немного выигрыша по размеру. S>Вы, кстати, уже попробовали что-то маленькое на C++ запустить на рутере? S>Я сталкивался с проблемой, отсуствия libstdc++.so (рантайма) на устройстве, что сводит на нет все попытки написания на C++.
Здравствуйте, malphunction, Вы писали:
M>Спасибо за ответы.
M>Попробую с map-файлами и binutils. M>Удивлен, что нет универсального решения, разве народ не занимается оптимизацией собственных программ по размеру? M>Для встраиваемых решений это же ещё актуально.
C>>Насчет зависимостей из stdlib — не совсем понимаю. Что там может быть такого большого?
M>Ошибся. Не stdlib, а шаблоны: мне нужны std::vector и std::string.
Чем больше методов у шаблонного класса используются, тем больше кода добавляется
Если vector используется для разных типов, то возможно компилятор не может оптимизировать все методы.
M>Тоже не ясно, как считать их размер? И стоит ли их как-то оптимизировать?
M>Я вот попытался написать свой аналог std::string на функциях strlen, strcat M>и т.п. -- выигрыш составил пару процентов, не стоило и браться
Вероятно есть libstdc++.so и реализация std::string береться оттуда.
Как вариант, попробуйте использовать больше библиотечных функций.
Здравствуйте, malphunction, Вы писали:
M>Удивлен, что нет универсального решения, разве народ не занимается оптимизацией собственных программ по размеру? M>Для встраиваемых решений это же ещё актуально.
Неа. На практически любой кристалл сейчас есть такой же, но с удвоенным размером памяти и на несколько копеек дороже, несопоставимо с зарплатой программиста. 140кб для АРМ — довольно-таки смешной размер.
По сути — наиболее эффективным будет избавится от printf, scanf и поддержки плавающей точки, если есть возможность. Ну и алгоритмическая оптимизация, если, опять же, есть возможность. Остальные способы дадут гроши.
Re[4]: Оптимизация размера программы: самые большие функции/
Здравствуйте, sz36, Вы писали:
S>Здравствуйте, malphunction, Вы писали:
M>>Удивлен, что нет универсального решения, разве народ не занимается оптимизацией собственных программ по размеру? M>>Для встраиваемых решений это же ещё актуально. S> Неа. На практически любой кристалл сейчас есть такой же, но с удвоенным размером памяти и на несколько копеек дороже, несопоставимо с зарплатой программиста. 140кб для АРМ — довольно-таки смешной размер.
Согласен; но моя проблема в том, что приходится писать под конкретную модель роутера;
после установки всех необходимых программ там остается вот те самые 140-160 Kb :(
S> По сути — наиболее эффективным будет избавится от printf, scanf.
А scanf и printf библиотечные же? Из libc, которая есть на роутере. Есть ли
смысл от них избавляться?
Re[4]: Оптимизация размера программы: самые большие функции/
Здравствуйте, Sanik, Вы писали:
S>Попробуйте добавить S>-fno-exceptions -fno-rtti
Да, от rtti можно избавиться, сегодня попробую. А вот exception'ы
в одном модуле задействованы, попробую их убрать.
S>Должно дать немного выигрыша по размеру. S>Вы, кстати, уже попробовали что-то маленькое на C++ запустить на рутере? S>Я сталкивался с проблемой, отсуствия libstdc++.so (рантайма) на устройстве, что сводит на нет все попытки написания на C++.
Да, моя программа на C++ (в том смысле, что использует std::* и несколько самописных классов, но без
других сишных наворотов). Если линковать динамически с libstdc++.so, то прога получается маленькой
(где-то 30 Kb), но сама библиотека не влезает в роутер :( Поэтому я использую статическую линковку,
как ниже предлагали. Прогу разбабахивает до 150-200 Kb. А это уже много.
Re[5]: Оптимизация размера программы: самые большие функции/
Здравствуйте, malphunction, Вы писали:
M>Здравствуйте, Sanik, Вы писали:
S>>Попробуйте добавить S>>-fno-exceptions -fno-rtti
M>Да, от rtti можно избавиться, сегодня попробую. А вот exception'ы M>в одном модуле задействованы, попробую их убрать.
S>>Должно дать немного выигрыша по размеру. S>>Вы, кстати, уже попробовали что-то маленькое на C++ запустить на рутере? S>>Я сталкивался с проблемой, отсуствия libstdc++.so (рантайма) на устройстве, что сводит на нет все попытки написания на C++.
M>Да, моя программа на C++ (в том смысле, что использует std::* и несколько самописных классов, но без M>других сишных наворотов). Если линковать динамически с libstdc++.so, то прога получается маленькой M>(где-то 30 Kb), но сама библиотека не влезает в роутер Поэтому я использую статическую линковку, M>как ниже предлагали. Прогу разбабахивает до 150-200 Kb. А это уже много.
Это собсвенно и есть основная проблема диетизации
Как неоригинальный вариант — избавиться от C++ зависимостей с помощью данной библиотеки и переделкой под C.
... << RSDN@Home 1.2.0 alpha 4 rev. 1477>>
Re[5]: Оптимизация размера программы: самые большие функции/
Здравствуйте, malphunction, Вы писали:
M>Согласен; но моя проблема в том, что приходится писать под конкретную модель роутера; M>после установки всех необходимых программ там остается вот те самые 140-160 Kb
Так если там ОС стоит, то с большой вероятностью в ней можно чего-нибудь "почикать". Пользуясь терминологией нашего, прости Господи, национального лидера. 30 кило совсем немного — может картинка какая, или ReadMe, или еще что-нибудь ненужное...
M>А scanf и printf библиотечные же? Из libc, которая есть на роутере.
Так Вы пишете, что статическую линковку используете? scanf и printf много за собой тянут, в частности, поддержку ПЗ (если она у Вас не используется).
Re[6]: Оптимизация размера программы: самые большие функции/
Здравствуйте, sz36, Вы писали:
S> Так если там ОС стоит, то с большой вероятностью в ней можно чего-нибудь "почикать". Пользуясь терминологией нашего, прости Господи, национального лидера. 30 кило совсем немного — может картинка какая, или ReadMe, или еще что-нибудь ненужное...
Почищено всё; даже комментарии из системных скриптов выпилены.
M>>А scanf и printf библиотечные же? Из libc, которая есть на роутере. S> Так Вы пишете, что статическую линковку используете? scanf и printf много за собой тянут, в частности, поддержку ПЗ (если она у Вас не используется).
Я статически линкую только libstdc++ (в другой ветке объяснено, почему), а libc есть на роутере -- с ней линкуюсь динамически.
Поэтому использование scanf/printf не раздувает прогу, как я понимаю.
Что такое ПЗ -- не понял.
Re[5]: Оптимизация размера программы: самые большие функции/
Здравствуйте, malphunction, Вы писали:
M>Здравствуйте, Sanik, Вы писали:
M>Да, моя программа на C++ (в том смысле, что использует std::* и несколько самописных классов, но без M>других сишных наворотов). Если линковать динамически с libstdc++.so, то прога получается маленькой M>(где-то 30 Kb), но сама библиотека не влезает в роутер Поэтому я использую статическую линковку, M>как ниже предлагали. Прогу разбабахивает до 150-200 Kb. А это уже много.
Тогда смысл разбираться с программой если она состовляет максимум 20% от бинарника?
По моему мнению ситуация следующая есть набор объектных файлов твоей программы,
собранных с ffunction-section, есть libstdc++.a — архив с объектныыми файлами
библиотеки C++, которые не собраны с ffunction-section, соотвественно,
когда происходит линковка самые большие куски не нужного тебе кода не выбрасываются.
И по-моему решение очевидно.
Re: Оптимизация размера программы: самые большие функции/мод