Что не так с использованием встроенных функций? - PullRequest
35 голосов
/ 14 сентября 2008

Хотя в некоторых ситуациях было бы очень удобно использовать встроенные функции,

Есть ли недостатки с встроенными функциями?

Заключение

Видимо, в использовании встроенных функций нет ничего плохого.

Но стоит отметить следующие моменты!

  • Чрезмерное использование встраивания может замедлить работу программ. В зависимости от размера функции, ее вставка может привести к увеличению или уменьшению размера кода. Встраивание очень маленькой функции доступа обычно уменьшает размер кода, тогда как встраивание очень большой функции может значительно увеличить размер кода. На современных процессорах меньший код обычно выполняется быстрее благодаря лучшему использованию кэша команд. - Правила Google

  • Преимущества встроенных функций в скорости уменьшаются по мере увеличения размера функции. В какой-то момент накладные расходы на вызов функции становятся небольшими по сравнению с выполнением тела функции, и выгода теряется - Источник

  • Есть несколько ситуаций, когда встроенная функция может не работать:

    • Для функции, возвращающей значения; если существует оператор возврата.
    • Для функции, не возвращающей никаких значений; если существует оператор loop, switch или goto.
    • Если функция рекурсивная. -source
  • Ключевое слово __inline вызывает функцию, которая будет встроена, только если вы укажете опцию оптимизации. Если указан параметр оптимизации, будет ли учитываться __inline, зависит от настройки параметра встроенного оптимизатора. По умолчанию встроенный параметр действует при каждом запуске оптимизатора. Если вы укажете оптимизировать, вы также должны указать опцию noinline, если хотите, чтобы ключевое слово __inline игнорировалось. -source

Ответы [ 12 ]

21 голосов
/ 14 сентября 2008

Стоит отметить, что ключевое слово inline на самом деле просто подсказка компилятору. Компилятор может игнорировать встроенный код и просто генерировать код для функции где-нибудь.

Основным недостатком встроенных функций является то, что они могут увеличивать размер исполняемого файла (в зависимости от количества экземпляров). Это может быть проблемой на некоторых платформах (например, встроенных системах), особенно если сама функция рекурсивна.

Я бы также порекомендовал сделать встроенные функции очень маленькими - Преимущества встроенных функций в скорости, как правило, уменьшаются по мере увеличения размера функции. В какой-то момент накладные расходы на вызов функции становятся небольшими по сравнению с выполнением тела функции, и выгода теряется.

14 голосов
/ 14 сентября 2008

Это может увеличить размер исполняемый, и я не думаю, компиляторы всегда будут на самом деле они встроены, даже если вы использовали встроенное ключевое слово. (Или это другой наоборот, как то Вайбхав сказал? ...)

Я думаю, что обычно нормально, если Функция имеет только 1 или 2 оператора.

Редактировать: Вот что говорится в документе linux CodingStyle :

Глава 15: Встроенная болезнь

Там, кажется, есть общее заблуждение, что у gcc есть магия "Ускорь меня" - опция ускорения называется "в соответствии". Хотя использование встроенных может подойдет (например, как средство о замене макросов, см. главу 12), это очень часто нет. Обильное использование встроенное ключевое слово приводит к гораздо большее ядро, которое в свою очередь замедляет система в целом, из-за больший объем памяти для процессора и просто потому, что там меньше память, доступная для кэша страниц. Просто подумай об этом; промах страницы вызывает поиск диска, который легко занимает 5 миллисекунд Есть много процессора циклы, которые могут войти в эти 5 милисекунд.

Разумное правило состоит в том, чтобы не встроить в функции, которые имеют больше чем 3 строки кода в них. Исключением из этого правила являются случаи где параметр известен как константа времени компиляции, и в результате этой постоянства вы знаете Компилятор сможет оптимизировать большинство вашей функции во время компиляции. Для хорошего примера этого более позднего случая, см. встроенную функцию kmalloc ().

Часто люди утверждают, что добавление inline к функциям, которые являются статическими и используются только один раз всегда победа, так как там нет космического компромисса. Пока это технически правильно, GCC способен вставляя их автоматически без помощь и вопрос обслуживания удаление встроенного, когда второй пользователь появляется перевешивает потенциальную ценность подсказки, которая говорит gcc сделать что-то, что он сделал бы в любом случае.

4 голосов
/ 16 сентября 2008

Существует проблема со встроенной функцией - после того, как вы определили функцию в заголовочном файле (которая подразумевает встроенную, явную или неявную, определяя тело функции-члена внутри класса), не существует простого способа изменить ее без принудительного пользователи перекомпилировать (в отличие от перекомпоновки). Часто это вызывает проблемы, особенно если рассматриваемая функция определена в библиотеке, а заголовок является частью ее интерфейса.

4 голосов
/ 14 сентября 2008

Как уже упоминалось, ключевое слово inline является лишь подсказкой для компилятора. На самом деле, большинство современных компиляторов будут полностью игнорировать эту подсказку. Компилятор имеет свою собственную эвристику, чтобы решить, следует ли встроить функцию, и, откровенно говоря, не хочет вашего совета, большое спасибо.

Если вы действительно, действительно хотите сделать что-то встроенное, если вы действительно его профилировали и посмотрели на разборку, чтобы убедиться, что переопределение эвристики компилятора действительно имеет смысл, то это возможно:

  • В VC ++ используйте ключевое слово __forceinline
  • В GCC используйте __attribute __ ((always_inline))

Ключевое слово inline имеет и второе, правильное назначение - объявление функций в заголовочных файлах, но не внутри определения класса. Ключевое слово inline необходимо, чтобы компилятор не генерировал несколько определений функции.

4 голосов
/ 14 сентября 2008

Согласен с другими постами:

  • inline может быть лишним, потому что компилятор сделает это
  • может встроить ваш код в код

Третий момент - это может заставить вас раскрыть детали реализации в ваших заголовках, например,

class OtherObject;

class Object {
public:
    void someFunc(OtherObject& otherObj) {
        otherObj.doIt(); // Yikes requires OtherObj declaration!
    }
};

Без встроенного объявления все, что вам нужно, - это предварительное объявление OtherObject. Со встроенным твой заголовок нуждается в определении для OtherObject.

2 голосов
/ 16 сентября 2008

Не знаю, связан ли мой ответ с вопросом, но:

Будьте очень осторожны с встроенными виртуальными методами! Некоторые ошибочные компиляторы (например, в предыдущих версиях Visual C ++) генерировали встроенный код для виртуальных методов, где стандартным поведением было ничего не делать, кроме как переходить по дереву наследования и вызывать соответствующий метод.

2 голосов
/ 14 сентября 2008

Я сомневаюсь в этом. Даже компилятор автоматически добавляет некоторые функции для оптимизации.

1 голос
/ 14 сентября 2008

Встраивание больших функций может сделать программу больше, что приведет к большему количеству пропусков кэша и замедлению работы.

Решить, когда функция достаточно мала, чтобы встраивание увеличило производительность, довольно сложно. Руководство по стилю Google C ++ рекомендует использовать только встроенные функции из 10 строк или менее.

1 голос
/ 14 сентября 2008

Следует также отметить, что встроенное ключевое слово является только запросом. Компилятор может решить не вставлять его, аналогично, компилятор может сделать встроенную функцию, которую вы не определили как встроенную, если он считает, что компромисс между скоростью и размером того стоит.

Это решение обычно принимается на основе ряда вещей, таких как настройка между оптимизацией по скорости (избегает вызова функции) и оптимизацией по размеру (встраивание может вызвать раздувание кода, поэтому не подходит для больших многократно используемых функций ).

с помощью компилятора VC ++ вы можете переопределить это решение, используя __forceinline

ТАК в общем: Используйте inline, если вы действительно хотите иметь функцию в заголовке, но в другом месте нет особого смысла, потому что если вы собираетесь что-то извлечь из этого, хороший компилятор все равно сделает ее встроенной для вас.

0 голосов
/ 25 июля 2016

Среди других проблем со встроенными функциями, которые я видел сильно злоупотребляющими (я видел встроенные функции из 500 строк), следует помнить следующее:

  • нестабильность сборки

    • При изменении источника встроенной функции все пользователи заголовка перекомпилируются
    • #include s утечка в клиента. Это может быть очень неприятно, если вы переделываете встроенную функцию и удаляете неиспользуемый заголовок, на который полагался какой-либо клиент.
  • исполняемый размер

    • Каждый раз, когда вместо инструкции вызова указывается inline, компилятор должен генерировать весь код inline. Это нормально, если код функции короткий (одна или две строки), и не очень хорошо, если функция длинная
    • Некоторые функции могут генерировать намного больше кода, чем кажется на первый взгляд. В данном случае речь идет о «тривиальном» деструкторе класса, который имеет много переменных, не являющихся членами модуля (или двух или 3 переменных-членов с довольно грязными деструкторами). Вызов должен быть сгенерирован для каждого деструктора.
  • время исполнения

    • это очень зависит от вашего кэша ЦП и разделяемых библиотек, но локальность ссылки важна. Если код, который вы, возможно, вставляете, хранится в кэше процессора в одном месте, ряд клиентов может найти код, не страдающий от пропадания кэша и последующего извлечения памяти (и, что еще хуже, в случае извлечения диска) , К сожалению, это один из тех случаев, когда вам действительно нужно провести анализ производительности.

Стандарт кодирования, в котором я работаю, ограничивает встроенные функции простыми установщиками / получателями и, в частности, говорит, что деструкторы не должны быть встроенными, если только у вас нет измерений производительности, чтобы показать, что встраивание дает заметное преимущество.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...