Измерение использования статической памяти для C++, портированной на встроенную платформу
Я создал небольшую программу в качестве подтверждения концепции для системы, которая должна быть реализована на встроенной платформе. Программа написана на C++11 с использованием std и скомпилирована для запуска на ноутбуке. Последняя программа, которая должна быть реализована позже, является встроенной системой. У нас нет доступа к компилятору встроенной платформы.
Я хотел бы знать, есть ли способ определить статическую память программ (размер скомпилированных двоичных файлов) разумным и сопоставимым способом, когда она должна быть перенесена на встроенную платформу. Требование состоит в том, что размер двоичного файла составляет менее 10 КБ. Наш двоичный файл имеет размер 700 Кбайт при компиляции и удалении со следующими флагами:
g++ options: -Os -s -ffunction-sections -fdata-sections
linker options: -s -Wl,--gc-sections
strip libmodel.a -s -R .comment -R .gnu.version --strip-unneeded -R .note
Это заняло 4 МБ, прежде чем мы использовали параметры полосы и оптимизации.
Я все еще далеко, и это не такая уж большая программа. Как я могу оправдать сравнение каким-либо образом с эквивалентной программой на встроенной платформе.
2 ответа
Обратите внимание, что размер двоичного файла может быть немного обманчивым в том смысле, что неинициализированные переменные, разделы.bss, не обязательно будут занимать физическое пространство в двоичном файле, так как они, как правило, просто отмечаются как присутствующие, фактически не имея места для них.... это обычно происходит загрузчиком ОС, когда он запускает вашу программу.
objdump
( http://www.gnu.org/software/binutils/) или, возможно, elfdump
или цепочка инструментов elf ( http://sourceforge.net/apps/trac/elftoolchain/) поможет вам определить размер различных сегментов, данных и текста, а также размер отдельных функций и глобальных переменных и т. д. Все это программы "заглядывают" в ваш скомпилированный двоичный файл и извлекают много информации, такой как размер раздела.text,.data, перечисляют различные символы, их расположение и размеры, и даже могут разбивать раздел.text...
Пример использования elfdump в образе ELF test.elf может быть elfdump -z test.elf > output.txt
, Это сбросит все, включая разбор текстового раздела. Например, из elfdump
в моей системе я видел
Section #6: .text, type=NOBITS, addr=0x500, off=0x5f168
size=149404(0x2479c), link=0, info=0, align=16, entsize=1
flags=<WRITE,ALLOC,EXECINSTR>
Section #7: .text, type=NOBITS, addr=0x24c9c, off=0x5f168
size=362822(0x58946), link=0, info=0, align=4, entsize=1
flags=<WRITE,ALLOC,EXECINSTR,INCLUDE>
....
Section #9: .rodata, type=NOBITS, addr=0x7d5e4, off=0x5f168
size=7670(0x1df6), link=0, info=0, align=4, entsize=1
flags=<WRITE,ALLOC>
Так что я могу видеть, сколько занимает мой код (разделы.text) и мои данные только для чтения. Позже в файле я тогда вижу...
Symbol table ".symtab"
Value Size Bind Type Section Name
----- ---- ---- ---- ------- ----
218 0x7c090 130 LOC FUNC .text IRemovedThisName
Итак, я вижу, что моя функция IRemovedThisName
занимает 130 байтов. Быстрый скрипт позволит вам перечислить функции, отсортированные по размеру, и переменные, отсортированные по размеру. Это может указать вам места для оптимизации...
Для хорошего примера objdump
попробуйте http://www.thegeekstuff.com/2012/09/objdump-examples/, в частности, раздел 3, в котором показано, как получить содержимое заголовков разделов с помощью -h
вариант.
Что касается того, как программа будет сравниваться на двух разных платформах, я думаю, вам просто нужно будет скомпилировать на обеих платформах и сравнить результаты, которые вы получаете от вашей obj/elfdump
в каждой системе - результаты будут зависеть от набора системных инструкций, от того, насколько хорошо может оптимизироваться каждый компилятор, от общих аппаратных архитектурных различий и т. д.
Если у вас нет доступа к встроенной системе, вы можете попробовать использовать на своем ноутбуке кросс-компилятор, настроенный для вашей конечной цели. Это даст вам двоичный файл, подходящий для встроенной платформы, и инструменты для анализа файла (то есть кросс-платформенная версия objdump
). Это дало бы вам некоторые цифры о том, как программа будет выглядеть на возможном встроенном sys.
Надеюсь это поможет.
РЕДАКТИРОВАТЬ: Это также поможет Как получить размер функции C изнутри программы на C или встроенной сборки?
Оказалось, что включенные библиотеки занимали огромное пространство (как было указано в комментарии) и, удалив их, можно было уменьшить размер почти до нуля в сочетании со следующими флагами:
set(CMAKE_CXX_FLAGS "-Os -s -ffunction-sections -fdata-sections -DNO_STD -fno-rtti -fno-exceptions")
set(CMAKE_EXE_LINKER_FLAGS "-s -Wl,--gc-sections")
И удаляя ненужный код, используя:
strip libmodel.a -s -R .comment -R .gnu.version --strip-unneeded -R .note
4 МБ можно уменьшить до 9,4 КБ, что ниже нашего лимита.
В итоге, std
занимает огромное количество места.