Накладные расходы в неиспользованном коде - PullRequest
12 голосов
/ 26 мая 2011

Мне интересно, каковы издержки использования неиспользуемых функций в вашем коде.

Скажем, например, что у вас есть некоторая запись в журнал отладки, и вы затем передаете большинству своих объектов функцию ToString (), которая используетсяв журналах отладки.

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

Или они просто делают исполняемый файл незначительно больше и в противном случае не влияют на производительность?например, не влияет на скорость?Или компилятор или компоновщик, возможно, даже удаляет функции, если они не используются?Если компилятор или компоновщик не удаляют код, что, если функции ToString () были определены встроенными?Предположительно, он попытается встроить код, а поскольку функция никогда не вызывается, она исчезнет?

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

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

Спасибо

Ответы [ 4 ]

5 голосов
/ 26 мая 2011

Это зависит от компилятора и, я думаю, от уровня оптимизации.

G ++ и MSVC ++ удаляют неиспользуемые встроенные функции, но сохраняют неиспользуемые не встроенные функции. Например, вы используете только небольшую часть STL в обычной программе. Все неиспользуемые функции удаляются, потому что они определены как встроенные.

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

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

3 голосов
/ 26 мая 2011

1. Относительно компиляторов и компоновщиков

Это действительно зависит от того, как вы создаете свой исполняемый файл.

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

Однако, если вы создадите динамическую связь, они будут там, потому что в отношении библиотеки они экспортируются и, следовательно, используются.

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

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

2. Как решить проблему?

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

Лично я бы не стал беспокоиться ... тем более, что я тоже захожу в Release (как еще отследить производственные проблемы?).

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

2 голосов
/ 26 мая 2011

Линкеры действительно удаляют дублирующиеся функции, и они удаляют несвязанные данные (линкер Microsoft предлагает переключатели /OPF:REF и /OPT:ICF для настройки этих параметров).

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

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

Еще одним преимуществом #ifdef является то, что он переносим и не зависит от конкретной системы компилятора: - /

0 голосов
/ 26 мая 2011

Если вы поместите не виртуальную функцию в отдельный файл в библиотеке, и ссылка статически, она должна быть добавлена ​​в исполняемый файл, только если используемый. Но единственная реальная разница будет в размере исполняемый файл; это может предположительно повлиять на местность, и, таким образом, производительность, но я был бы очень удивлен, если бы это когда-либо имело реальное значение на практике. В общем, я бы сказал, что эта техника не стоит возиться в приложении. (Если вы поставляете сторонние библиотеки, с другой стороны, вы определенно хотите, чтобы каждая не виртуальная функция в отдельный файл.)

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