Является ли это разумным хаком для встроенных функций через единицы перевода?
Я пишу чувствительный к производительности код, который действительно требует, чтобы я вызывал определенные вызовы функций.
Для встроенных функций, которые совместно используются единицами перевода через заголовок, обычно нужно поместить определение функции в файл заголовка. Я не хочу этого делать. Некоторые из этих функций работают со сложными структурами данных, которые не должны отображаться в заголовке.
Я обошел это, просто включив все файлы.h и.c по одному разу в один файл.c, чтобы была только одна единица перевода. (Это замедляет повторную компиляцию, но не настолько, чтобы иметь значение.)
Это было бы "проблемой решено", но это исключает получение ошибки, когда функция в одном C-файле вызывает функцию в другом C-файле, который должен быть закрытым, и я хочу получить ошибку в этом случае. Итак, у меня есть отдельная запись Makefile, которая выполняет "нормальную" сборку, просто для проверки этого случая.
Чтобы заставить функции, объявленные inline, хорошо воспроизводиться в "нормальной" сборке, я фактически определяю макрос may_inline, который используется там, где обычно находится атрибут inline. Он определяется как пустой для обычной сборки и определяется как "встроенный" для оптимизированной сборки.
Это кажется приемлемым решением. Единственный недостаток, который я могу видеть, - это то, что у меня не может быть закрытых функций в разных.c файлах, которые имеют один и тот же прототип, но до сих пор это не было для меня большой проблемой.
Другое потенциальное решение состоит в том, чтобы использовать GCC Link-Time Optimization, которая должна позволять встраивание между единицами перевода. Однако это новая функция, и я не верю, что она всегда делает все так, как хотелось бы. Кроме того, я могу заставить его работать только на тривиальных проблемах, а не на моем собственном коде.
Это приемлемый взлом или я делаю что-то невероятно глупое? Тот факт, что я никогда не видел этого, заставляет меня немного нервничать.
0 ответов
Unity build - абсолютно верный подход, и он широко используется в промышленности с незапамятных времен (см., Например, этот пост). Последние версии Visual Studio даже предоставляют встроенную поддержку для них.
У LTO есть и недостаток: она не переносима даже между компиляторами для одной и той же платформы.