Есть ли реальный пример, когда inline отрицательно влияет на производительность программы на C?
Во многих дискуссиях о inline
Ключевое слово в объявлениях функций, кто-то укажет, что это может на самом деле замедлить вашу программу в некоторых случаях - в основном из-за взрыва кода, если я прав. Я никогда не встречал такого примера на практике. Что такое реальный код, где использование inline
Можно ли ожидать, что это нанесет ущерб производительности?
2 ответа
Ровно 10 лет и один день назад я сделал этот коммит в OpenBSD:
http://www.openbsd.org/cgi-bin/cvsweb/src/sys/arch/amd64/include/intr.h.diff?r1=1.3;r2=1.4
Сообщение коммита было:
deinline splraise, spllower и setsoftint. Делает ядро меньше и быстрее. deraadt@ хорошо
Насколько я помню, двоичный файл ядра сократился более чем на 100 КБ, и не удалось создать ни одного тестового примера, который стал бы медленнее, а несколько тестов макросов (например, компиляция ядра) были заметно быстрее (5-10%, если я правильно помню, но не цитируйте меня)
Примерно в то же время я отправился на поиски реальных измерений встроенных функций в ядре OpenBSD. Я нашел несколько, которые имели минимальный прирост производительности, но большинство из них имели 0 измеримых результатов, а некоторые делали вещи намного медленнее и были убиты. По крайней мере, еще одно исключение оказало огромное влияние, и это были внутренние макросы malloc (где идея заключалась в том, чтобы встроить malloc, если он имел размер, известный во время компиляции) и распределители буфера пакетов, которые сократили ядро на 150 КБ и имели значительную производительность. улучшение.
Можно предположить, хотя у меня нет никаких доказательств, что это потому, что ядро большое, и мы изо всех сил стараемся оставаться внутри кеша при выполнении системных вызовов, и каждый кусочек помогает. Так что в этих случаях на самом деле помогло только сокращение двоичного файла, а не количество выполненных инструкций.
Представьте себе функцию, которая не имеет параметров, но требует интенсивных вычислений с постоянным числом промежуточных значений или использованием регистров. Затем вставьте эту функцию в код, имеющий постоянное количество промежуточных значений, или зарегистрируйте использование тоже.
Отсутствие параметров делает процедуру вызова более легкой, поскольку не требуются никакие операции со стеком, требующие много времени.
Когда это встроено, компилятору приходится сохранять много регистров и передавать другие для использования с новой функцией, воспроизводя процесс регистров и резервного копирования данных, необходимых для вызова функции, возможно, в худшем случае.
Если операции резервного копирования являются более обширными, с точки зрения времени и машинных циклов, по сравнению с механизмом вызова функции, особенно если функция вызывается экстенсивно, то это имеет пагубный эффект.
Похоже, это относится к некоторым конкретным функциям, широко используемым в ОС.