Комментарии 34
Статья интересная (без шуток) - спасибо!
Но все таки - как уменьшить кодовую базу? Потому что, например, ваш пример с дешаблонизацией кодовую базу только увеличит.
там если уходить от виртуал не получается нужен общий конструктор и ситуации всякие
https://godbolt.org/z/jc5vPaPW6 ну у меня так получилось
В embedded мире часто приходится жертвовать идиоматичностью и красотой кода ради соответствия жестким ограничениям по памяти или производительности, пример с дешаблонизацией как раз из этой оперы - код становится чуть сложнее для чтения, но зато прошивка влезает в чип
if (std::holds_alternative<std::string>(some_variant)) {
auto v = *std::get_if<std::string>(&some_variant);
// какие-то действия с v
}Зачем тут holds_alternative?
Используя holds_alternative проще и быстрее сразу проверить: содержит ли some_variant значение типа строки (без извлечения этого значения), чем сразу с помощью std::get_if извлекать из варианта нечто и для неудачных исходов обрабатывать nullptr.
Или у вас другое мнение?
Ох. Мне кажется, вам пока не хватает интуиции в таких низкоуровневых делах. Проверяйте себя бенчмарками или Godbolt. Свою точку зрения обосновывать, конечно же, не буду
Вам специально для таких случаев дали новую форму оператора if:
if (auto ptr = std::get_if<std::string>(&some_variant)) {
// какие-то действия с *ptr
}
Всё вполне читаемо, но на одну строчку меньше и быстрее. Если не хочется ставить кучу "звёздочек" - можно добавить auto v = *ptr;, строчек будет столько же, но кода меньше.
holds проверяет но get_if как я понял тоже проверит они оба берут значение из варианта, наверно(ну да я не уверен)
Чтобы убедиться, что в варианте лежит строка
Все равно при вызове
push_backбудет проверка: не переполнился ли вектор, не надо ли снова аллоцировать. Поэтому тут мы остановились на варианте сstd::vector<std::unique_ptr>без резервации.
Но почему push_back?) C emplace_back было бы компактнее))
std::vector<std::unique_ptr<I>> v;
v.emplace_back(new A);
v.emplace_back(new B);Если я правильно помню, это утечка памяти, если emplace_back кинет исключение
Так все конструкторы у unique_ptr - они noexcept.
Ну, есть вариант, что контейнер память не сможет выделить, то так ли стоит переживать об утечках, если память кончилась?)
нет, вам правильно сказали. Если не получится выделить память при reserve в векторе, то вылетит исключение и указатель просто повиснет
Как я и сказал - это наименьшая из проблем
А вот и нет :) Я сходил в стандарт (см. раздел util.smartptr.shared.const)
template<class Y> explicit shared_ptr(Y* p);
...
If an exception is thrown, delete p is called
when T is not an array type, delete[] p otherwise
И
template<class Y, class D> shared_ptr(Y* p, D d);
...
If an exception is thrown, d(p)
is called.
Начиная с С++17 такое поведение гарантированно стандартом.
UPD
Прошу прощения, забыл что речь шла про unique_ptr. Но гарантии там те же.
emplace_back - шаблонная функция, поэтому на каждый тип будет генерироваться новая функция.
Выкидывание лишнего барахла, которое GNU-шный компилятор по одним ему ведомым причинам оставляет в исполняемом файле - дело хорошее. Но вот менять сам код, чтобы сэкономить какие-то крохи размера файла - сомнительная затея. Идиоматичность кода должна быть важнее его итогового размера. Да и сколько так можно сэкономить в итоге? Десять килобайт на мегабайт исполняемого файла? Стоит ли овчинка выделки?
Стоит ли овчинка выделки?
В случае из статьи, у вас нет выбора. На старых устройствах просто не хватает памяти для новых прошивок. И поэтому приходится оптимизировать, что бы хоть как-то обновлять старые устройства.
Ответ на ваш вопрос в самом начале статьи:
На старых платформах уже нет возможности расширить накопитель
Овчинка стоит выделки, когда альтернатива - это сказать заказчику, что его дорогое железо больше не будет получать обновления
Полезный разбор полезный, но хотелось бы увидеть больше цифр. Например, "включили флаг -Os - выиграли 200 КБ. Заменили std::visit - еще 50 КБ. Перешли с shared_ptr на unique_ptr - 30 КБ". Без этого сложно оценить реальный вклад каждого из методов
Хозяйке на заметку:
Из интервью с автором Total Commander - Кристианом Гислером. 2011 год
-- Широко известный факт, что вы до сих пор пишете свой файл-менеджер Total Commander на "допотопном" Delphi 2. С чем это связано?
-- Я являюсь обладателем лицензионных версий всех последних Delphi, поэтому достаточно хорошо представляю себе их возможности. Но дело тут вот в чем: компиляция exe-файла в Delphi 2 дает на выходе файл ощутимо меньший по размеру, чем, например, в Delphi 7. Кроме того, тестирование показывает, что exe-шник из-под Delphi 2 работает заметно быстрее, чем его полный аналог, выпущенный компилятором Delphi 7. Я сталкиваюсь с тем, когда люди часто удивляются, что Total по-прежнему работает очень быстро - я собираюсь сохранить эту его особенность, и, отчасти, секрет тут в правильно выбранном компиляторе.
...разработка 32-битной версии TC останется на Delphi 2.
...Добавлю, что кроме этого Delphi 2 генерирует очень универсальный код, например, с полной поддержкой 16-битных приложений или Windows 95/98 - у меня до сих пор хватает таких клиентов.
пора, брат, пора.
Я у себя столкнулся с такой особенностью виртаульных таблиц.
У меня был код, который использовал базовый класс как интерфейс, но сами реализации не хранились в одном месте через указатель на этот базовый класс. Но сам базовый класс имел виртуальный деструктор, как советуют core гайды.
Удаление этого деструктора, сэкономило мне около 10К в бинарнике.
Утечек нет, потому что не используется владение через указатель на этот базовый класс и деструктор вызывается всегда сразу у потомка.
базовый класс имел виртуальный деструктор, как советуют core гайды
Без виртуального деструктора будет неопределенное поведение, если будет вызван деструктор через базовый класс. Как вы от этого защитились? Сегодня не используется владение через указатель на базовый класс, а завтра появится.
Сегодня не используется владение через указатель на базовый класс
Именно так
Ну и как тут уже упоминали
В embedded мире часто приходится жертвовать идиоматичностью и красотой кода ради соответствия жестким ограничениям по памяти или производительности
Поменяется код придется руками исправлять, забудешь исправить - сам дурак. Это же c++.
Для запуска Bloaty с отладочным файлом используется флаг
--debug-file.
bloaty --debug-file=/path/to/debug_symbols_file /path/to/my_stripped_executable
А есть инструкция как этот правильно применяется? Допустим собрали вы свой проект с описанными флагами для оптимизации включая --strip-all, с gcc на линукс с cmake. Где искать `/path/to/debug_symbols_file` ?
Есть ли возможность помочь с этим вопросом?
https://habr.com/ru/companies/timeweb/articles/793152/comments/#comment_29169604
Как сделать так, чтобы между секциями isr_vector и text не было заполнения?
.isr_vector 0x08000000 0x194
0x08000000 isr_vector_start = .
0x08000000 . = ALIGN (0x4)
*(.isr_vector)
.isr_vector 0x08000000 0x194 build/startup_stm32f401xe.o
0x08000000 g_pfnVectors
0x08000194 isr_vector_end = .
0x08000194 . = (ADDR (.isr_vector) + SIZEOF (.isr_vector))
.text 0x080001c0 0x39758
0x080001c0 text_start = .
0x080001c0 . = ALIGN (0x4)У меня сейчас 0x080001c0-0x08000194 = 44 байта впустую зря пропадают.
Информация
- Сайт
- yadro.com
- Дата регистрации
- Дата основания
- Численность
- 5 001–10 000 человек
- Местоположение
- Россия
- Представитель
- Ульяна Соловьева
Отсекая лишнее: как сократить бинарный код программы на C++ и не потерять нужную функциональность