Подтвердить что ты не робот

Оптимизация включения заголовка

Есть ли автоматический способ оптимизации включения файлов заголовков в С++, чтобы улучшить время компиляции? Со словом "автоматический" я имею в виду инструмент или программу. Можно ли найти, какие файлы заголовков устарели (например, открытая функциональность не используется)?

Изменить: каждый заголовок include включает в себя только один раз, это одна важная вещь, но есть ли способ изменить содержимое файлов, так что часто используемые "функциональные возможности" относятся к конкретным включенным и менее часто используемая функциональность на других включает в себя? Я слишком много спрашиваю? К сожалению, мы говорим о существующей базе кода с тысячами файлов. Может ли это быть инструментом рефакторинга, о котором я действительно прошу?

Спасибо.

4b9b3361

Ответ 1

Update

Я думаю, что вы действительно хотите "включить то, что используете", а не минимальный набор заголовков. IWYU означает, что объявить как можно больше вперед, и включать заголовки, которые прямо объявляют используемые вами символы. Вы не можете бездумно преобразовать файл в IWYU, поскольку он больше не может компилироваться. Когда это произойдет, вам нужно найти отсутствующий заголовок и добавить его. Однако, если каждый файл очищается IWYU, ваши компиляторы будут быстрее в целом, даже если вам приходится добавлять заголовки изредка. Не говоря уже о том, что заголовки будут больше значимые/самодокументированные.

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

Теперь, если бы у вас была большая часть работы по рефакторингу репликации IWYU:)


Я подумал о создании/использовании такого инструмента один раз. Идея заключается в использовании бинарного поиска и повторной компиляции, чтобы найти минимальный набор включений. При дальнейшем расследовании это не показалось полезным.

Некоторые проблемы:

  • Изменение включенных файлов заголовков может изменить поведение и все равно разрешить компиляцию файла. Один пример, в частности, если вы определили свой собственный std::swap в отдельном файле заголовка. Вы можете удалить этот заголовок, и ваш код будет компилироваться с использованием стандартной реализации std::swap. Тем не менее, std::swap может быть: неэффективным, вызывать ошибку во время выполнения или, что еще хуже, создавать неверно неправильную логику.

  • Иногда включение заголовочного файла работает как документация. Например, для использования std::foreach, часто включая <vector>, достаточно, чтобы его компилировать. Код более значим с дополнительным #include <algorithm>.

  • Минимальный набор компиляции не может быть переносимым, между компиляторами или версиями компилятора. С повторением примера std::foreach нет гарантии, что std::foreach будет предоставлен <vector>.

  • Минимальный набор включений не может существенно повлиять на время компиляции. Поддержка Visual Studio и gcc #pragma once, которые делают повторное включение существенно несуществующей производительности. И по крайней мере gcc-препроцессор был оптимизирован для обработки, включив защиту очень быстро (так же быстро, как #pragma once).

Ответ 2

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

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

Ответ 3

PC-Lint будет сообщать о неиспользуемых файлах include.

Ответ 4

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

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

Ответ 5

В блоге GamesFromWithin есть хорошая статья о заголовках С++ и даже инструмент, который перечисляет, какие заголовки включены больше всего (и таким образом, основные кандидаты на pimpl/pch/forwarding). Хороший инструмент, хотя и в perl, и я фактически использовал его несколько раз, чтобы выкопать некоторые хорошие данные, когда время сборки заставляет меня (слишком много) орехов.

Ответ 6

Я никогда не слышал о каком-либо бесполезном включении инструмента. И это будет только тривиальный случай.

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

Ответ 7

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

Рекурсия по всем файлам h/cpp в проекте.
Для каждого он искал #includes и добавлял//перед каждым из них по очереди, а затем запускал сборку. Если сборка вернула ошибку, она отключит //. Если сборка выполнена успешно, она оставила включенную строку комментария.

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

Он сделал небольшое, но существенное различие (около 5 минут на 70-минутной сборке IIRC).

Ответ 8

Недавно я нашел инструмент, который бы точно сделал то, что вы просили.

В блоге Ben Ziegler Double Buffered, он опубликовал около оптимизировать систему оптимизации.

Итак, я придумал сложный решение Brute Force Perl Script. В принципе, я бы просматривал все .c файлы в нашем коде и попытка прокомментировать каждый #include директивы. Затем он перекомпилирует базы кода и посмотреть, есть ли ошибки. Если бы это было, это вернулось бы комментарий, а затем перейти к следующий.

Результаты не были звездными. Нет заметных улучшений времени сборки.

Я все еще поддерживаю свой первый ответ; это пустая трата времени и не рекомендуется.

В любом случае это его perl script. Вам нужно немного взломать его, чтобы заставить его работать с вашим кодом, но ядро ​​должно работать одинаково.

Ответ 9

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

Ответ 10

Предварительно скомпилированные заголовки ужасны.

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