Дмитpий Hecтepук

Блог о программировании — C#, F#, C++, архитектура, и многое другое

Распределенная разработка и проект FreeSpace

13 комментариев

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

С чего все начиналось

Когда я обитал в сфере финансового программирования (было же такое), одна из задач была в том, чтобы “сливать” воедино финансовые показатели из различных источников. Начиналось все достаточно просто – берем какую-то котировку, делаем для нее квантизацию (это когда нужно подсчитать агрегированные значения за последнюю минуту/час/день и т.п.) а потом начинаем считать всякие показатели (к пр. движимое среднее). Сейчас такие задачи делаются с помощью Reactive Extensions, под которым, должен сказать, аггрегаторы и квантизаторы выглядят не лучшим образом. Тогда же это делалось более примитивными методами. Но не суть…

Так вот, в те времена подход GPGPU был не ахти какой популярный, и соответственно все утыкалось в слабый перформанс моего одноядерного процессора. И, естественным путем, я набрел на то, что по-хорошему нужно использовать несколько машин чтобы все эффективно считать. Механизмы общения между компьютерами в те времены были ни ахти какие, соответственно использовались такие извращения как NServiceBus/MSMQ которые, конечно, имеют свои приемущества, но все же “не айс”.

Самым прикольным было написать консоль, которая показывала бы как моя сеть в realtime обсчитывала те или иные показатели. Более того, в те времена я также использовал нейронные сети (MLPs w/backpropagation) и у меня даже остался код, которые по объектным моделям сетей генерировал диаграммы в PowerPoint. Забавное было зрелище.

Сети – это же так соблазнительно!

Качество работы на среднестатистической “винде” прогрессивно снижается. Когда я начинал программировать на Visual Studio 97, в моем компьютере было 16Мб (мегабайт!!!) RAM, но при этом все работало. Сейчас такой experience можно получить разве что скачав EVC++ 4 (завидую эмбедщикам!). У нас же в плане разработки все плохо – сплошные тормоза. Вон только вчера коллега рассказал, что получил удовольствие от использования Visual Studio 2008 для части ReSharper SDK. Когда я его спросил что у него за машина, оказалось что и 16Gb RAM и SSD у него присутствуют. Так что делаем выводы…

Все это наводит на достаточно печальные мысли. Компьютеры будут становиться быстрее, но “затыки” в производительности будут, и со временем они будут все больше и больше. А нам нужно разрабатывать, а не ждать 15 минут пока полсотни референсов в проект добавятся (таргет-файлы рулят!).

Поэтому единственная вменяемая стратегия, к которой я на данный момент пришел сводится к следующим вещам.

Во-первых, я ратую за экологичное программирование, т.е. если вы используете машину для разработки, не стоит на ней ставить доменный контроллер, IIS, AppFabric и еще 100500 различных сервисных примочек. Ни в коем случае не стоит ставить серверные технологии которые используют SQL Server т.к. эта штука сама по себе съест 1-2Gb оперативки, так она еще и будет диск дергать даже когда никто к ней не обращается. А потом, в один прекрасный день, вы увидите что вместо того чтобы разрабатывать, вы думаете как бы засунуть SQL Server’ный кэш в RAM. Или что-то в этом духе.

Во-вторых, я за распределенную разработку. Писать код можно и на одном компьютере. Но держите свои затраты к минимуму. Ставьте десктопную ось (да-да, сейчас модно ставить 2008R2 везде где не попадя, я тоже на это попался в свое время). Если можете себе это позволить – ставьте XP. Windows, VS и ReSharper/dotTrace/dotCover/TortoiseXxx – плагины, естественно по вкусу. Остальное – в топку! А точнее на другой компьютер.

Что это дает?

Я уже слышу крики в стиле “мне всего и так хватает!”. Что же, если вам итак хорошо, рад за вас. Это как извечная дискуссия про мониторы – каждому свое. Но если говорить о приемуществах такого подхода, то их масса.

Главное приемущество – это моментальный фидбэк. Представьте, что у вас есть солюшн который собирается, скажем, две минуты. Две минуты – это вечность. Особенно если билд провалился с какой-то дурацкой ошибкой которую не отловил статический анализатор. Да, мы говорим не про простенькие проектики, мы говорим например про системы где смешан С++ (адски медленная компиляция), C# и Java (да-да, Java – она примешана тут осознанно). Если учесть сложность cross-VM конфигов, все это дело работает не так быстро как хотелось бы.

Так вот, представьте себе систему, где фидбэк по сборке, тестам, и даже покрытию (хотя с покрытием сложнее) получается моментально. Причем он никак не затрагивает ваш разработческий комп, т.к. мы договорились держать его стерильным. Моментальный фидбэк стоит многого! Особенно это затрагивает такую проблему как тестирование на staging-серверах. На Хабре был пост про то, надо ли стабить репозитарии. Так вот что я думаю – если вы можете себе это позволить, тестируйте на staging-базах! Главное чтобы эти тесты не вызывали затыков. А если вызывает затыки – просто добавьте воды машин!

Второе приемущество – это то, что ничего не отвлекает. Я категорически против подхода, когда люди в свою Студию устанавливают 1000 различных дополнений для всяких микро-фич которые, особенно если они используют визуальные элементы, тормозят все до такого состояния, что работать невозможно. Но я не столько про стороннии фичи говорю, сколько про два основных источника потери времени – компиляцию и тестирование. Давайте обсудим их более детально.

Компиляция

Разработчики С++ уже давно поняли что сборка проектов должна быть распределенной, и на рынке есть для этого соответствующие решения. Но если вы думаете, что в .Net все лучше, то вы правы только отчасти. Да, .Net собирается быстрее, хотя я уверен что новый C#5 компилятор будет намного медленнее в силу своей managed структуры. Опять же, еще один аргумент в том, что де нынче MSBuild поддерживает параллелизацию напрямую, и тем самым грамотное использование MSBuild вместе с правильной, loosely coupled архитектурой, как бы избавляет нас от проблем с медленной компиляцией.

А вот и нет!

На практике все сводится к следующим моментам. Во-первых, стоимость компиляции связана не только с созданием сборок – компиляция как таковая включает в себя массы различных процессов, таких как кастомные task-и которые вы используете. Например, процесс XSLT-трансформации путем какого-нть community task‘а может стоить намного больше чем компиляция.

Во-вторых, этот аргумент не применим на mixed-mode проектах. С++ играет по своим правилам, особенно если вы делаете что-то сложное. Да, ваша сборка может скомпилироваться параллельно с другими. Но это не покрывает изначальную проблему – она скомпилируется медленно. Это, кстати, влияет не только на С++ — даже тот же F# компилируется медленнее (что понятно), не говоря уже про языки вроде Scala (reminder: Scala компилируется в 10 раз медленнее Java).

В третьих, все как-то забыли что некоторым проектам нужно собирать несколько конфигураций. В этом случае параллелизация на уровне конфигураций имеет смысл – тут мы билдим staging, а тут – production. Естественно, никто не мешает настроить разные конфигурации на разных build-системах. Действительно, на практике многие разработчики используют TeamCity для параллелизации подобных задач. Одна из самых популярных – параллелизация тестирования. Кстати о нем…

Тестирование

Тестирование бывает разным. Одно дело когда вы нажали F5 на проекте, который открывает VS в дебаг-режиме. Если у вас комп с 4Gb RAM и Раптором – вы попали. Можете смело идти за кофе/чаем/печеньками. Отладочный экспириенс будет адским. Да – и не думайте что удаленная отладка вам поможет. Во-первых, вы замахаетесь ее настраивать (у меня на это полдня ушло), но даже настроив, вы сразу поймете, что игра не стоит свеч – идея неплохая, но скорость – улиточная. Snail speed. Если действительно хочется делать отладку на другой машине, более вменяемым решением мне лично кажется использование VMWare Workstation. Но так или иначе, тормоза будут.

Но я сейчас немного не про это, а скорее про банальное unit/integration-тестирование. Сейчас в этой сфере ведется работы по разным направлениям – например работы связанные с автопрогоном только тех тестов, которые были затронуты изменениями в коде. Примеры таких программ – NCrunch и Mighty Moose. А теперь угадайте, какой основной смысл этих программ? Правильно – экономия ресурсов. Вызывать только те тесты которые были затронуты. А не все подряд.

На самом деле, это очень сложная задача. В чем проблема вызова абсолютно всех тестов? Правильно, в том, что эти тесты могут задевать сотню различных систем. Да-да, я не только про юнит-тесты говорю, но и про интеграционные тесты – включая те, которые например дергают реальные базы или устройства. Их-то тоже хочется тестировать, причем опять же вопрос ставится так: если мы можем тестировать постоянно – почему бы не делать это? Лично я – ярый сторонник непрервыного тестирования. И не только по комиту – а например по любому компилу. Сделал тестовую сборку – она сразу же ушла в тестирование. Если что упало – результаты сразу же возвращаются к разработчику.

Так что там про FreeSpace?

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

FreeSpace использует XMPP (в частности – библиотеку MatriX) и механизмы облачной синхронизации файлов. XMPP гарантирует что машины могут беспрепятственно коммуницировать между собой, при условии что у вас стоит XMPP-сервер (поставить какой-нть ejabberd занимает полминуты). А механизмы облачной синхронизации позволяют гарантировать, что на всех инстансах одни и те же файлы. Поскольку сервис работает через MEF, файлы можно обновлять динамически.

Основная цель FreeSpace – балансировка нагрузки, т.е. составление сбалансированных планов исполнения. Собственно выполнение задач на себя берут уже готовые тулзы. Для компиляции, например, это может быть MSBuild, для тестирования – Gallio. Суть в том, что имея информацию о всех нодах в сети, а также агентах на этих нодах (на одной ноде можно бегать более одного агента), можно сформировать сбалансированный план компиляции или тестирования, который оптимально использует все доступные ресурсы и при этом уважает предпочтения самого нода, т.е. знает что нельзя перегружать нод, который уже занят или имеет какие-то другие обязанности.

Одно из приемуществ FreeSpace – системе полностью плевать на домены. Синхронизация через XMPP способна игнорировать все firewall’ы и протаскивать трафик через порт 80, если это надо (ну, это теоретически… это нужно тестировать). При этом трафик можно шифровать, так что идея о том что де кто-то украдет контрольные данные в транзите или подменит их тоже отпадает. А сами файлы синхронизуются с помощью изначально безопасной системы (так по крайней мере нам говорят), поэтому кроме как на нодах к ним не достучаться. И даже достучавшись, система-то распределенная, так что всей картины все равно не получите – хотя конечно подразумевается, что нодам вы доверяете.

Более сложные задачи

Есть более сложные задачи, которые пока не решить ну никак. Во-первых, было бы здорово вынести за пределы компьютера разработчика весь статический анализ и сделать некий ‘FxCop/R#/whatever as a service’. Если это сделать, и если это хоть как-то параллелизуемо (есть подозрение что не очень), это позволит делать намного более глубокий/затратный анализ и тем самым получать намного более умные эвристические подсказки.

Покрытие – запредельно затратная операция, поэтому вынести его наружу тоже хотелось бы. Это, правда, менее приоритетная задача, т.к. я не большой фанат покрытия. Но с другой стороны, имея уже готовый механизм для измерения покрытия (к пр., dotCover), я не вижу никаких причин не применять измерение покрытия, скажем, к разным тестовым фиксчам на разных машинах. Главное чтобы можно было слить все результаты воедино и как-то их продемонстрировать. (Прошу заметить, что в отличии от результатов тестирования, результаты покрытия таки требуют наличие локальной Visual Studio для подсветки и навигации. То же отчасти верно и для обычного юнит-тестирования, хотя там и не нужно вклиниваться в редактор.)

Зато что я люблю так это всякий спекулятивный процессинг. Я бы с удовольствием воспользовался, например, механизмами мутационного тестирования. Ну или например я бы с радостью гонял тесты на производительность параллельных алгоритмов варьируя разные параметры, такие как, к примеру, degree of parallelism.

Вместо заключения

FreeSpace разрабатывается в первую очередь не как коммерческий продукт, а как система, которая сможет, при наличии достаточного количества машин, существенно сэкономить количество времени, требуемое для работы с крупными проектами. Соответственно, пишу я ее в основном для себя, с уклоном в те проблемы (например, тестирование в виртуальной среде – VMM/HyperV) которые являются для меня наиболее насущными.

Я давно не писал в этот блог, но теперь буду писать почаще, особенно если кому-то данная тема покажется интересной. И естественно, я выпущу дистрибутив системы как только у меня будет что релизить. Основной concern в данном случае в том, что я очень хочу сделать систему обновляемой, чтобы она и ее плагины (я использую плагин-архитектуру на основе MEF) могли автоматически обновляться по мере выхода новых версий.

А пока всё! Comments welcome! ■

Advertisements

Written by Dmitri

16 июня 2011 в 23:00

Опубликовано в .NET, Computation, Development

Tagged with ,

комментариев 13

Subscribe to comments with RSS.

  1. Вот это
    http://code.google.com/p/qizmt/

    помоему может заменить весь этот огород?

    relan

    16 июня 2011 at 23:25

    • не уверен, что использование такого map reduce движка в такой относительно несложной задаче не будет оверхедом

      Trukhin Yuri

      16 июня 2011 at 23:31

    • С этой штукой я знаком, но такой уровень сложности мне ни к чему.

      Dmitri

      17 июня 2011 at 7:42

  2. Очень интересная разработка, хотя нужно потрогать сначала, потом делать выводы. Точнее идея интересная, важно, чтобы это все было достаточно просто в настройке. Сложные конфигурации служебных утилит видеть уже не хочется. Что касается XMPP — это необычный способ использования протокола… А в чем преимущество его например перед WCF Peer-To-Peer на 80м порту? (именно P2P в WCF я не использовал еще, но теоретически почему бы и нет). И интересно, как это все будет инициироваться (запуск задач) и результаты будут собираться тоже через xmpp?

    Trukhin Yuri

    16 июня 2011 at 23:29

    • XMPP намного проще по сравнению с WCF. Конфигурации — минимум. Паттерны request-response и pub-sub идут «из коробки». XMPP используется для всего — например, чтобы запустить распределенные тесты, мы посылаем команды на соответствующие машины. Результатом вызова Gallio.Echo является тоже XML-файл. На хосте который запустил задачу мы собираем эти XML-файлы воедино.

      Dmitri

      17 июня 2011 at 7:46

  3. Стоит ли все это делать ради 15 минут ожидания компиляции? Я вот склоняюсь, что раз в час-два отдохнуть минут 15 тоже полезно.

    muradovm

    17 июня 2011 at 12:39

    • Это стоит делать не то что ради 15, а даже ради 2-х минут. Помните, что компиляция делается не только ради самой компиляции, но чтобы тесты можно было прогнать.

      Dmitri

      17 июня 2011 at 14:33

  4. Меня немного смущает зацикленность на распределенности. По идее с данной задачей должен справляться один удаленный build-сервер. На мой взгляд, сначала было бы логичнее добиться хорошего распараллеливания на одной удаленной машине, а уже во второй версии добавить распределенность.

    А вообще, тема классная. Мечтаю, чтобы build вместе с прогонкой тестов проходил мгновенно :)

    Как автору того поста про репозитории, мне интересно ваше мнение на этот вопрос. Ведь дело там не только в производительности…

    Alexander

    17 июня 2011 at 20:34

    • Тут суть в том, что на отдельно взятом билд-сервере мы уже можем оптимизировать вещи настолько, насколько это возможно – в частности, мы можем распараллелить по ядрам/процессорам как компиляцию (MSBuild) так и тестирование (MbUnit’s [Parallelizable]). Агенты у нас тоже есть (VS, TeamCity), и разбросать их по сети не сложно.

      Проблема в том, что это все равно медленно. Это не real-time и даже близко к нему не стоит. А я предлагаю чтобы компиляция+тестирования проходило за минимальное время. Понятное дело что этот же механизм, в последствии, можно и для “непрерывной интеграции” подключить, но пока что я больше беспокоюсь об отдельно взятом разработчике, который хочет знать, сколько тестов он сломал. И знать как можно быстро чтобы если появилась регрессия, можно было сразу пофиксить.

      Что касается репозитариев… это философский вопрос, и по-хорошему нужно стабить/мокать все что ни попадя и писать “правильные” юнит-тесты. Де факто, если вы прижаты во времени, то имхо можно тестировать и на живой базе. Особенно если у вас есть распределенная инфраструктура которая может развернуть 10 разных конфигураций этих баз на разных машинах. Собственно для этого я и запустил этот проект.

      Dmitri

      18 июня 2011 at 9:11

  5. Интересная идея!

    В подкасте меня удивило утверждение, что для каждой виртуалки нужная своя физическая карточка. И VmWare, и VirtualPC, и VirtualBox умееют эмулировать работу сети даже при полном отсутствии физической карточки(обычно они устанавливают свою виртуальную карточку).
    Для связи с хост-машиной можно поставить Loopback карточку.

    bashor

    17 июня 2011 at 23:17

    • Строго говоря — да — сети можно эмулировать. Проблема в том, что мне нужно чтобы виртуалки — хотя бы часть из них — были полноценными членами моего, невиртуального, интранета. Я еще на ранней стадии раскапывания всей темы с виртуалками, только начал копаться в VMM, но запас NIC’ов держу на всякий случай.

      Dmitri

      18 июня 2011 at 8:56

  6. ссылк на bitbucket у вас битая — написано bUtbucket

    bashor

    18 июня 2011 at 10:51


Оставить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: