Каков наилучший подход к кодированию в среде медленной компиляции?

15

Я привык кодировать на C # в стиле TDD - написать / или изменить небольшой фрагмент кода, пересобрать за 10 секунд все решение, заново запустить тесты и снова. Легко...

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

Моя производительность все еще в порядке для небольших проектов, но она ухудшается, когда с увеличением размера проекта и после того, как время компиляции достигает 10+ минут, это становится действительно плохо. И если я найду ошибку, мне придется снова начать компиляцию и т. Д. Это просто расстраивает.

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

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

комар
источник
stackoverflow.com/questions/5078409/… Вероятно, они должны быть объединены / в одном месте.
Бен Л
См. Laso stackoverflow.com/questions/373142/… для ускорения времени компиляции C ++.
Затмение
2
Начни бой на мечах . ; p
Стивен Джеурис
В последний раз я использовал C ++ всерьез, используя предварительно скомпилированные заголовки, сократив время компиляции в четыре раза.
gnasher729

Ответы:

16

Несколько вещей приходят мне на ум:

  1. Используйте распределенную компиляцию . Вы можете сделать это с помощью GCC («distCC»?) Или VC ( IncoreiBuild от Xoreax не совсем дешевый, но стоит каждого потраченного на него цента).

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

  3. Программа против небольших тестовых проектов, а не всего большого приложения.

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

  5. Инвестируйте в оборудование . Большее количество ядер ЦП (на вашей машине или в других) может удивить распределенной компиляцией, и много памяти плюс быстрый диск (SSD вместо HDD) очень помогут. Если у вас 64-битная система и неприличное количество оперативной памяти, компиляция на диске RAM может обеспечить невероятный прирост скорости.

SBI
источник
1
кеш компилятора на самом деле лучше, чем распределенная компиляция в моем опыте.
pqnet
Говоря о дисках RAM и SSD, я был весьма удивлен, что это не принесло такого увеличения скорости компиляции. Мой текущий проект (Java на Android) компилируется из чистого состояния за ~ 45 секунд с SSD и за ~ 40 секунд с RAM-диска (и весь набор инструментов находится на RAM-диске, а не только в источниках). Не существенное увеличение, я бы сказал.
Haspemulator
10

Другое техническое решение, еще не упомянутое другими, - это переход на твердотельные накопители вместо обычных жестких дисков. В предыдущем проекте, над которым я работал, твердотельные накопители сократили время сборки с 30 минут до 3.

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

Петер Тёрёк
источник
6
Это интересно. Это говорит о том, что 90% времени сборки составляют задержки ввода-вывода.
Майк Данлавей
Я не видел снижения на 90%, но существенного. Кажется, это не ускоряет компиляцию, но определенно ускоряет линковку. Если вы вносите небольшие изменения в большой проект (так что в изменениях не так уж много компиляции) и перекомпоновываете, вы вполне можете это получить. (Это Visual Studio 2008, использующая C ++.)
Дэвид Торнли
1
Это хорошая идея. Кроме того, монтирование части оперативной памяти в вашей файловой системе будет работать быстро и дешево.
Горан Йович
2
Рамдиск еще быстрее (и дешевле).
SK-logic
1
@John: Да, хорошо написанный компилятор должен (ИМХО) быть привязанным к вводу / выводу.
Майк Данлавей
3

Больше планирования, код в больших блоках, написание интеграционных тестов вместо модульных тестов и запуск сборки build + test suite в одночасье.

Неманья Трифунович
источник
3

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

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

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

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

jwenting
источник
1
Мальчик, это ситуация из ада. Я помню дни мэйнфреймов. Мы провели много «проверок» кода. Удивительно, как много было сделано таким образом, например, бесконечные симуляции полетов на Луну.
Майк Данлавей
3

Я легко помню, когда сборка заняла много времени. Некоторые смягчающие подходы:

  • Сборка системы путем объединения библиотек или библиотек. Таким образом, когда вы изменяете некоторый код, единственная часть, которую нужно перекомпилировать, это ваша часть.
  • Количество точек в коде, которое необходимо отредактировать для реализации функции, влияет не только на объем редактирования, а на частоту, с которой вы вносите ошибки, усиливая цикл compile-debug-edit-compile. Помогает все, что уменьшает избыточность кода, например DRY.
  • Если вы находитесь в отладчике и можете редактировать, перекомпилировать и продолжать работу, не выходя из отладчика, это действительно полезно.
Майк Данлавей
источник
2

10+ минут для компиляции? Шутки в сторону?

Используете ли вы IDE, которая делает наращивание (например, Eclipse)? Если нет, то, вероятно, так и должно быть, он будет выполнять базовую компиляцию в считанные секунды, а не минуты.

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

TrueDub
источник
5
10 минут мало. Я работал над проектом, который занял час, чтобы скомпилировать и связать с нуля одноядерный компьютер, PCH и все такое. Конечно, за исключением сборок с автоматическим выпуском, никто не будет строить его только на одном ядре процессора, но все же ... Если вам нужно что-то изменить в заголовке, который включен почти везде (манипулирование строками, обработка ошибок), вы можете сойти с ума.
ВОО
2
Раньше работал (несколько лет назад) в системе, на компиляцию которой ушло 48 часов. Конечно, полная сборка началась только в пятницу вечером, надеюсь, будет завершена, когда мы вернемся в офис в понедельник. Вместо этого мы создавали небольшие модули по мере необходимости (скажем, одну DLL).
С
2
-1 ко всем комментариям выше, если бы я мог +1 к TrueDub. Да, если вы все перекомпилируете, это может занять очень много времени. Однако, если вообще задуматься об управлении зависимостями, то 10-часовые проекты перекомпиляции могут иметь инкрементную перекомпиляцию менее чем за минуту, что является нормой. Вам всем должно быть стыдно за то, что вы тратите время своих работодателей на ожидание ваших перекомпиляций, поскольку использование небольшого количества интеллекта сэкономит огромное количество времени.
Данк
2
И если вы работаете в небольшом магазине, который работает над проектом с несколькими MLoC, то это означает, что значительная часть кода устарела, и началась десять лет назад как несколько небольших проектов, где скорость компиляции никогда не была проблемой, и управление зависимостями ужасно плохо. Так вы собираетесь сказать такой компании выбросить все это и потратить еще десять лет на ее переписывание?
ВОО
2
@Dunk: Это была небольшая компания с менее чем дюжиной разработчиков, работающих над проектом с несколькими MLoC. Это очень отличается от сотен разработчиков делают так: вы не можете повторно писать что - то с нуля, потому что вам нужно лет , чтобы сделать это. Как бы я ни ненавидел эту идею, инвестирование в распределенную компиляцию было экономически целесообразным, а переписывание - нет. О, и я унаследовал эти интерфейсы. :-xЯ не был там десять лет назад, когда они были придуманы. (Я изменил большую часть этого кода, чтобы использовать TMP, чтобы найти больше ошибок при компиляции и меньше в поле.)
sbi
2

Во-первых, почему сборка занимает так много времени?

  • Поддерживает ли ваша среда (IDE, make, что угодно) инкрементные сборки? Убедитесь, что вы перекомпилируете только изменения, а не все.
  • Если у вас многоядерный компьютер, ваша IDE может поддерживать параллельную компиляцию. Я точно знаю, что Visual Studio делает это. По-видимому, так же делает GCC. Так что получите лучшую машину и включите параллельную компиляцию.
  • Рассмотрите возможность использования предварительно скомпилированных заголовков.
  • Если вы попробуете все это, а компиляция все еще будет медленной, просмотрите ваш код. Ищите ненужные зависимости. Включаете ли вы заголовок, в котором будет достаточно предварительного уведомления? Подумайте об использовании языка PIMPL, чтобы уменьшить зависимость от заголовков.

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

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

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

Дима
источник
2
Я не уверен, поддерживает ли GCC параллельные компиляции настолько, насколько тот факт, что make или подобные инструменты запустят несколько копий GCC, если вы скажете это тоже.
Захари К
1
+1 за PIMPL. Я работал над проектом, когда время сборки вышло из-под контроля. В этом проекте я не заботился о том, сколько других заголовков было включено в каждый заголовок. В моем следующем проекте я решил минимизировать это, широко используя PIMPL. Время сборки остается отличным, хотя второй проект, вероятно, в два раза больше первого.
Джейсон Б,
1

Вам, вероятно, нужен многоплановый подход:

1) Быстрее строить системы. Столько ядер / RAM / быстрый диск, сколько вы можете себе позволить. Для более крупных проектов C ++ вы обнаружите, что диск часто является ограничителем, поэтому убедитесь, что у вас есть быстрые.

2) Больше модульности проекта. Разбейте вещи так, чтобы изменения не могли легко вызвать полную перекомпиляцию всего. Честно говоря, поместите как можно больше базовых вещей в отдельные файлы dll / so, чтобы часть проекта могла быть полностью отделена от остальных.

3) Инкрементные сборки / распределенные сборки / кэширование в соответствии с вашей средой. В некоторых системах distcc (распределенная сборка) и ccache (кэширование частично собранных компонентов) могут сэкономить много времени на компиляцию.

4) Убедитесь, что ваша сборка хорошо распараллелена. Особенно в среде make-файлов нетрудно попасть в ситуацию, когда вы случайно настроили Make-файлы так, что вы не можете выполнять параллельное построение.

Майкл Кон
источник
0

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

При работе с довольно сложными алгоритмами или бухгалтерией может быть полезно включить сильно упрощенную версию параллельно с «реальной». В любом случае, у вас есть полезные справочные данные включены.

Йорис Гир
источник
0

Что @sbi и @Michael Kohne сказали.

Потратьте время и энергию на сам процесс сборки. Когда-то у нас был величественный, зрелый продукт, для сборки которого потребовалось более часа. Много времени и энергии было потрачено на исправление предполагаемых зависимостей сборки, а затем - на исправление / уменьшение того, чем они были на самом деле. Время сборки сократилось до ~ 30 минут.

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

Это привело нас к тому, что все отдельные команды компиляции можно было выполнять параллельно. 'distcc' на медленных машинах, make / scons -j8 на многоядерных машинах. Это привело к полной сборке до нескольких минут.

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

Рик Берге
источник