Сколько накладных расходов при вызове функции в C ++? - PullRequest
58 голосов
/ 28 сентября 2008

Много литературы говорит об использовании встроенных функций, чтобы «избежать накладных расходов при вызове функции». Однако я не видел количественных данных. Каковы фактические накладные расходы при вызове функции, т. Е. Какого увеличения производительности мы достигаем путем встраивания функций?

Ответы [ 16 ]

0 голосов
/ 23 сентября 2017

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

  • Сохранить параметры функции в стеке
  • Сохранить адрес возврата в стеке
  • Перейти к начальному адресу функции
  • Распределить пространство для локальных переменных функции (стек)
  • Запустить тело функции
  • Сохранить возвращаемое значение (стек)
  • Свободное место для локальных переменных или сборщик мусора
  • Перейти к сохраненному обратному адресу
  • Освободите сохранение для параметров и т.д ...

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

0 голосов
/ 09 февраля 2016

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

  1. Использование функции динамической библиотеки с внешним связыванием в большинстве случаев приведет к полной обработке кадров стека.
    Вот почему использование qsort из библиотеки stdc на один порядок (в 10 раз) медленнее, чем использование кода stl, когда операция сравнения так же проста, как целочисленное сравнение.
  2. Также будет затронуто прохождение функциональных указателей между модулями.
  3. Такое же наказание, скорее всего, повлияет на использование виртуальных функций C ++, а также других функций, код которых определен в отдельных модулях.

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

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

Здесь есть несколько проблем.

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

  • Если функция виртуальная, то, конечно, вы заплатите цену, которую нельзя встроить, поскольку цель определяется во время выполнения. И наоборот, в Java вы можете платить эту цену, если не указали, что метод является окончательным.

  • В зависимости от того, как ваш код организован в памяти, вы можете платить за пропуски в кэше и даже пропуски страниц, поскольку код находится в другом месте. Это может иметь огромное влияние в некоторых приложениях.

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

У меня тоже нет номеров, но я рад, что вы спрашиваете. Слишком часто я вижу людей, пытающихся оптимизировать свой код, начиная с туманных представлений о накладных расходах, но не осознавая этого.

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

Для большинства функций, они не являются дополнительными накладными расходами для их вызова в C ++ против C (если только вы не считаете, что указатель «this» является ненужным аргументом для каждой функции. Вы должны каким-либо образом передавать состояние функции). ..

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

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

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

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