Який найкращий підхід для кодування в умовах повільної компіляції


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 ( Xoreax 'IncrediBuild не зовсім дешево, але варто витратити кожен цент, витрачений на це.).

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

  3. Програма проти малих тестових проектів, а не всієї великої програми.

  4. Використовуйте шаблон-мета-програмування для виконання алгоритмів під час компіляції . Так, це фактично збільшить час компіляції, але це також зменшить повороти, необхідні для тестування: якщо вона складе добре, це буде зроблено.

  5. Інвестуйте в обладнання . Більше ядер процесора (на вашій машині чи інших) буде дивуватися розподіленій компіляції, і багато пам’яті плюс швидкий диск (SSD замість HDD) дуже допоможуть. Якщо у вас 64-бітова система і нецензурна кількість оперативної пам’яті, компіляція на диску RAM може забезпечити неймовірне збільшення швидкості.


1
кеші компіляторів насправді є кращою ідеєю, ніж розподілена компіляція за моїм досвідом.
pqnet

Говорячи про диск оперативної пам’яті проти SSD, я був дуже здивований, що це не принесло стільки збільшення швидкості компіляції. Мій поточний проект (Java на Android) збирається з чистого стану за ~ 45 секунд від SSD і за ~ 40 секунд з диска оперативної пам'яті (і весь ланцюжок інструментів знаходиться на диску оперативної пам’яті, а не лише джерелах). Я б не сказав різкого збільшення.
Haspemulator

10

Іншим технічним рішенням, про яке ще не згадували інші, є перехід на твердотільні диски замість звичайних жорстких дисків. У попередньому проекті, над яким я працював, SSD знизили час нарощування з діапазону від 30 хвилин до 3.

Звичайно, вони коштують дорого. Для свого шефа обчисліть ціну втраченого часу розробника проти ціни одноразової інвестиції. Інвестиція, ймовірно, окупиться за кілька місяців.


6
Це цікаво. Це говорить про те, що 90% часу складання - це затримка диска вводу / виводу.
Майк Данлаве

Я не бачив зниження на 90%, але істотного. Здається, це не прискорює компіляцію, але, безумовно, прискорює зв'язок. Якщо ви вносите невеликі зміни у великий проект (так що компіляція не має великої кількості змін), і повторно посилаєтесь, ви можете це отримати. (Це Visual Studio 2008, використовуючи C ++.)
Девід Торнлі

1
Це гарна ідея. Крім того, встановлення частини оперативної пам’яті у вашій файловій системі працюватиме швидко, і це дешево.
Горан Йович

2
Рамдіск ще швидший (і дешевший).
SK-логіка

1
@John: Так, добре складений компілятор повинен (IMHO) бути пов'язаним введенням / виводом.
Майк Данлаве

3

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


3

Тривалий час компіляції іноді є проблемою, але вже згадана модуляція може допомогти подолати це (в основному).

Набагато серйозніше застрягає в середовищі, коли ви взагалі не можете скласти компіляцію, де кожна зміна коду повинна бути подана в інший відділ іншого континенту для застосування до середовища тестування / розробки, процес, який може зайняти кілька днів.

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

У таких умовах ви намагаєтеся зробити так само впевненим, що жодних помилок, перш ніж навіть намагатися скласти свій код, не потрібно. Це відчувається майже так, як я повернувся до програмування на мейнфреймі, де у нас було 5 хвилин процесорного часу на місяць для всіх компіляційних та тестових робіт.


1
Хлопчик, така ситуація з пекла. Я пам'ятаю дні мейнфрейму. Ми зробили багато "робочої перевірки" коду. Дивно, скільки зроблено таким чином, як нескінченні симуляції польотів на Місяць.
Майк Данлаве

3

Я легко згадую, коли тривали тривалий час. Деякі пом'якшувальні підходи:

  • Побудуйте систему, комбінуючи бібліотеки або dll. Таким чином, коли ви змінюєте якийсь код, єдина частина, яку потрібно перекомпілювати, - це ваша частина.
  • Кількість балів у коді, яку потрібно відредагувати, щоб реалізувати функцію, впливає не лише на кількість редагувань, які потрібно зробити, але і на частоту, з якою ви вводите помилки, посилюючи цикл compile-debug-edit-compile. Все, що зменшує надмірність коду, наприклад DRY, допомагає.
  • Якщо ви знаходитесь у відладчику і можете редагувати, перекомпілювати та продовжувати, не виходячи з налагоджувача, це справді корисно.

2

10+ хвилин для компіляції? Серйозно?

Чи використовуєте ви IDE, що робить інкрементальну забудову (наприклад, Eclipse)? Якщо ні, то, ймовірно, слід, це буде робити базове складання за секунди, а не за хвилини.

Або ви говорите про інтеграційні речі, де вам потрібно створити весь додаток, щоб перевірити свої зміни? Якщо так, погляньте на менші тести, щоб переконатися, що основні помилки не вийшли з коду, перш ніж виконувати повну збірку.


5
10 хвилин невеликий. Я працював над проектом, який займав годину, щоб скласти та зв'язати з нуля на одноядерній машині, PCH та ін. Звичайно, за винятком побудови автоматичного випуску, ніхто не будуватиме його лише на одному ядрі процесора, але все-таки ... Якщо вам довелося щось змінити в заголовку, який включений майже скрізь (маніпуляція з рядками, обробка помилок), ви можете зірватися.
sbi

2
Використовувався для роботи (років тому) у системі, для складання якої потрібно було 48 годин. Звичайно, повноцінна побудова була тільки колись розпочата в вечір п'ятниці, сподіваємось, що це буде зроблено, коли ми повернулися до офісу в понеділок. Ми замість цього побудували невеликі модулі за потребою (скажімо, одну DLL).
1111 року

2
-1 до всіх коментарів вище, якщо я міг би поставити +1 до TrueDub. Так, якщо ви перекомпонуєте все, то це може зайняти дуже багато часу. Однак якщо будь-яка думка взагалі приділяється управлінню залежностями, то нормою 10-годинних рекомпіляційних проектів можуть бути додаткові перекомпіляції менше ніж за хвилину. Ви всі повинні соромитися себе, витрачаючи роботодавців час, чекаючи ваших перекомпіляцій, коли застосуєте трохи інтелекту, заощадите величезну кількість часу.
Данк

2
І якщо ви працюєте в невеликому магазині, який, здається, сидить над проектом на кілька MLoC, то це означає, що значна частина коду є старою, розпочату десятиліття тому як безліч малих проектів, де швидкість компіляції ніколи не була проблемою, і управління залежністю гидко погано. То ви збираєтесь сказати такій компанії відкинути все це і провести ще одне десятиліття, переписавши його?
sbi

2
@Dunk: Це була невелика компанія, в якій працювало менше десятка розробників, що працювали над проектом Multi-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) Переконайтеся, що ваша конструкція може бути добре паралельною. Особливо в умовах makefile, не важко потрапити в ситуацію, коли ви випадково встановили Makefiles таким чином, що не можете робити паралельне будівництво.


0

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

Маючи справу з досить складними алгоритмами чи веденням бухгалтерського обліку, може бути корисним включити дуже спрощену версію паралельно з «реальною». У будь-якому циклі у вас є корисні довідкові дані.


0

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

Витратьте час та енергію на сам процес збирання. Колись у нас був чудовий, зрілий продукт, який потребував більше години для повного нарощування. Багато часу і енергії було витрачено на виправлення залежностей побудови, а потім на виправлення / зменшення того, що вони насправді були. Час побудови впав до ~ 30 хвилин.

Зміна інструментів побудови зменшила його більше. У проекті, що складається з декількох частин, "scons" може робити всі компіляції, перш ніж робити посилання. 'make' за допомогою декількох файлів виконує компіляцію одного проекту до посилань цього проекту, а потім рухається далі.

Це призвело до того, що всі окремі команди компіляції можна було робити паралельно. 'distcc' на повільних машинах, make / scons -j8 на багатоядерних машинах. Це призвело до того, що повна кількість знизилася до кількох хвилин.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.