Previous Entry Share Next Entry
photo25

Clean не нужен (repost)

очень правильно вот.

Оригинал взят у tonsky в Clean не нужен
Когда-нибудь задумывались, зачем в билд-системах команда clean? То есть, понятно, почему она в них была, но почему она до сих пор есть? Почему иногда билд собирается только с чистого листа?

Это все от бедности. Сравнение файлов по дате модификации. Переписывание билд-артефактов. Инкрементальный билд это кэш, а инвалидация кэша — одна из самых сложных задач в CS. Естественно, она всегда будет решаться с ошибками.

Единственная вещь, которая идеально кэшируется это неизменяемые данные. get_cached(file_name) будет ломаться, get_cached(digest(file_content)) нет. Естественно, туда можно (нужно) еще всего напихать, типа окружения, версии компилятора, флагов, цели. Но смысл в том, что кэш по контенту работает сам, успевай только мусор подбирать. Главное — корректность.

Это подтверждает успех гуглового Bazel: ненадежные билды на makefiles вдруг стали железно надежными, стоило им перейти на такую схему. Это может быть и было дорого на 386-х, но сейчас один фильм на диске весит столько, сколько ваши разработчики не нагенерируют артефактов за все время жизни проекта.

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

Следующий логичный шаг — положить артефакты в сеть. Идеально закешированный, гарантированно работающий артефакт нет смысла каждому разработчику собирать заново. Я не нашел никакой информации о том, делает ли это Гугл, но было бы логично. Ну а дальше граф разматывается с конца: сначала проверяем, закэширован ли самый высокоуровневый артефакт, если нет, смотрим, от чего он зависит, ищем кэши зависимостей, и т.д.

Ладно мы, динамщики, у нас билды недолгие, единственно противно что ломаются при рассинхроне. Но все вот эти ребята, которые на C++ игры пишут и у которых ночной «чистый» билд по шесть часов, они как до сих пор к этой схеме не пришли? Это же классическое «лучше день потерять». Причем даже терять много не придется, система простая как тряпка. Зато окупаемость, о, мне сложно представить ее масштабы.

В идеале, конечно, понятия билда вообще не должно существовать. Билды не имеют отношения к работе программиста, это просто формальный, неудачный шаг. Зато их отсутствие целый пласт проблем снимает. JS, Python, Clojure все делают правильно. Но если уж делать билд, непонятно, почему не сделать его надежным и правильным. Таким, чтобы не было отдельного понятия «инкрементальный билд», чтобы любой билд был инкрементальным, быстрым, с распределенным кэшем. И чтобы я больше ничего о команде clean не слышал.


  • 1
ady_1981 May 30th, 2015
ClojureScript имеет инкрементную компиляцию.
Erlang имеет механизм перегрузки состояния системы (правда, не во всех случаях, конечно).

tonsky May 31st, 2015
Именно! И она ломается.
Про Erlang не понял, но тулчейн у него ужасный, один из самых плохих, на уровне Makefiles.

ady_1981 May 31st, 2015
>Про Erlang не понял, но тулчейн у него ужасный, один из самых плохих, на уровне Makefiles.

Это не так:
1) есть стандартный сборщик проекта - rebar (это аля lein "лайт" :)).
2) есть sync - модуль, который перекомпилирует и перегружает модули, которые изменились.
3) Есть "Code Replacement": http://www.erlang.org/doc/reference_manual/code_loading.html#id83918

black_angel_by May 30th, 2015
Для C/C++ есть Ccache.
kernel вполне себе умеет инкрементальную сборку.
И что ж такого надо накодить, чтоб билд собирался 6 часов ? У меня даже webkit и libreoffice собираются максимум за 1.5 часа

Edited at 2015-05-30 09:05 pm (UTC)

juan_gandhi May 31st, 2015
ну хм, если для построения вебсервера GWS надо было, в частности, скомпилировать компилятор джаваскрипта, ну и т.д.

tonsky May 31st, 2015
Влад, по секрету, был в гугле общий сетевой кэш билд-артифактов, или фраза «каждый разработчик может собрать у себя любой проект гугла из исходников» означает что все-таки все, до самого начала, надо было собирать локально?

tonsky May 31st, 2015
Вы так говорите, будто 6 часов это ужас-ужас, а 1,5 это нормально

justy_tylor May 31st, 2015
Бред какой-то. Проблема не в cached и даже не в "hash vs. mtime".

По хорошему всё выражается как вызовы функций, с регистрацией замыканий, топосортом и мемоизацией. Но сборка билда осуществляется не монолитным сэндбоксом, а разными инструментами. Поведение которых может зависеть от неявных аргументов - локаль, таймзона, что-то ещё в env, что-то в состоянии файловой системы недалеко от компилятора, в сеточке, etc. Пока хоть один из инструментов выдаёт неучтённое западло по зависимостям или эффектам - проблемы будут. И можно заранее обезопасить работу популярных версий популярных инструментов, но не всего юнихвей-гадюшника, и, тем более, не пользовательских скриптов.

tonsky May 31st, 2015
> Но сборка билда осуществляется не монолитным сэндбоксом, а разными инструментами.

Это в C++. Проблемы же не только у C++, но и там, где инструмент один.

> И можно заранее обезопасить работу популярных версий популярных инструментов, но не всего юнихвей-гадюшника, и, тем более, не пользовательских скриптов.

Юниксвэй-гадюшник только жечь нахрен.

justy_tylor May 31st, 2015
Одним инструментом даже в хипстоте под jvm не ограничиться, ибо подготовка и проверка целостности ресурсов.

juan_gandhi May 31st, 2015
Сегодня все празднуют gittorrent.

amarao_san May 31st, 2015
У питона (некоторых программ) с билдами тоже все плохо. Не смотря на отсутствие makefile'ов.

blacklion May 31st, 2015
Следующий логичный шаг — положить артефакты в сеть. Идеально закешированный, гарантированно работающий артефакт нет смысла каждому разработчику собирать заново.
Вы изобрели Maven Central. И это пиздец, я хочу вам сказать.

tonsky May 31st, 2015
Почему? Весь java-мир пользуется (и Clojure, и Скала), все работает. В чем проблема? Надеюсь вы не переносите проблемы maven как тулзы сборки на проблемы, которые создает централизованный репозиторий?

blacklion May 31st, 2015
Да я тоже пользуюсь, но мавен -- говно страшное. В частности, потому что он енфорсит модель центрального репозитория (возможно, не уровня мира а уровня фирмы, но всё равно).

Я уже не говорю про его скорость работы. И про удобство написания XML'я. И про общую архитектуру.

Честное слово, мне с makefiles проще, чем с мавеном, не говоря уже о том, что make завершает сборку тогда, когда мавен ещё pom.xml парсит.

blacklion May 31st, 2015
Ну то есть, я профилировал от скуки. Наш проект с очень скромным набором зависимостей (инкаких спрингов с гибернейтами) и репозиторием внутри фирмы собирается по mvn clean install (я даже не говорю про clean deploy) порядка 10 минут на моей машине без SSD.
Из этого 75% времени занимает буккипинг мавена и 25% работа javac и упаковка jar'ов.
Просто mvn install в корне при изменении 3-4 файлов исходников меняет это соотношение на 90:10.

Это, по-моему, полный и лютый пиздец.

И я ещё не вспоминаю мои мучения как мейнейнера пакетов с мавен-проектами. Заставить мавен увидеть библиотеки, стоящие в системе, что бы не лазать НИКУДА а просто взять JAR'ы из /usr/local/${dependency}/lib -- это очень нетривиальная задача в большинстве случаев. Эта вот идеология, что во время СБОРКИ можно куда-то лезть ПО СЕТИ -- это вообще для меня, как для сисадмина и около, рак мозга. Вот они JAR'ы, в CLASSPATH лежат, заткнись и собирай!

sleepy_drago May 31st, 2015
сборка с нуля сишечки вышитой крестиками это отсилы 1 час распределенки. сборка "продукта" в товарном виде с нуля спокойно может занять полдня намного большей распределенки. собирать семейство продуктов на каждый чейндж - так никто не делает, кроме гуглей с фейсобуками и те по ходу чтобы поприкалываться. Мир давно живет на инкрементных тулзах просто автору почему-то скрипты ближе. То есть дон кихот воюет с мельницами позапрошлого века махая бумажным скриптовым копьем. glhf как говорится.

tonsky May 31st, 2015
Конечно, я рассказываю только о том что вижу и знаю. Расскажите, как делают инкрементальную сборку, на чем живет мир

sleepy_drago May 31st, 2015
ключевое слово - продукт это на 99% объема данные. У каждой отрасли свои ессно.
В коробках цифровых развлечений это "мир" в котором клиента развлекают. Сборка "всего" мира из исходников штука очень тяжелая, а если целевых платформ 3 или более, то тем более. Тестировщики живут базовыми версиями с "патчами" от создателей собираемыми сильно распределенно. То есть если базовую версию удается иметь каждый день то "патчи" делают почти все из сотен тружеников-строителей мира. Мир часто побит на несколько репозиториев контроля версий просто в силу разнотипности данных и реже распределенности команд. иметь команду в одном месте сейчас практически нереально. Возникает ситуация когда скрипты и логика максимально вынесены в визуальные инструменты и оторваны от "традиционного кода" от слова совсем.

пысы я как раз ездил в гости к тем кто держит основную билд ферму =) и по дороге назад такой наброс =) пытался написать комент по вайфаю но реконнект его съел =)

mbr May 31st, 2015
А что делать с константами, инлайновыми функциями и препроцессором? Особенно препроцессором.

wizzard0 June 1st, 2015
Вместо препроцессора, вносящего неявные зависимости - существуют гигиенические макросы.

Link-time code generation и whole program optimization это да, сложная штука, но никто не мешает кэшировать обьектники помельче.

(с метаданными)

Edited at 2015-06-01 09:07 am (UTC)

mbr June 1st, 2015
Т.е., давайте усложним систему сборки, перепишем код, но зато не будем использовать clean? Не стоит оно того.

mbr June 1st, 2015
> Вместо препроцессора, вносящего неявные зависимости

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

sab123 June 1st, 2015
Clean безусловно нужен, как минимум чтобы обнаруживать ситуации, когда итеративный билд работает, а чистый - нет, потому что генерация какого-то файла оказалась или утеряна напрочь, или работает в два прохода. Между прочим, в линуксных дистрибуциях в этом вопросе имеется редкая жопа.

Кеширование, естественно, все делают. То, как оно сделано в гугеле, мне очень напомнило, как оно делалось в ско, так что скорее всего корни у них обоих растут из белл лабса.

mbr June 2nd, 2015
Голос разума.

  • 1
?

Log in

No account? Create an account