суббота, 8 февраля 2014 г.

Зарисовка из жизни: опыт борьбы за производительность сборочного сервера (окончание)

Продолжение истории о борьбе с деградацией производительности сборочного сервера.

В прошлой заметке я остановился на том напряежённом моменте, когда специалист из IT-отдела признал их ответственность за деградацию производительности сервера и даже подтвердил то письмом.

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

Впрочем, временное средство для облегчения ситуации со сборкой всё же было найдено. Раз сеть замедляла обращение к виртуальному диску, расположенному вне хоста, надо было заменить этот "трудный" ресурс чем-то, расположенным внутри хоста, чего было в достатке. Очевидным стало решение с переносом сборки на RAM disk.

Чтобы это решение "взлетело", пришлось решить две небольшие проблемы:
1. Поскольку объем виртуального диска был ограничен, пришлось подправить build process workflow таким образом, чтобы он удалял все файлы после сборки.
2. Сборка вызывала много активности во временном каталоге (например, инструментарий WiX этим отличился), так что пришлось и его перенаправить на RAM disk.

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

Эти идеи нашлись в форме использования тех ресурсов, которые оказались в нашем распоряжении практически случайно. У нас остались рабочии станции двух уволившихся ранее сотрудников, о которых наши  IT-шники попросту забыли. Нет худа без добра: безалаберность их отдела, приведшая к бедам на виртуальной инфраструктуре, открыла нам нетрадиционную возможность для решения наших проблем :)

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

вторник, 4 февраля 2014 г.

Зарисовка из жизни: опыт борьбы за производительность сборочного сервера (начало)

Сразу скажу, какой-то особой морали в этой истории нет. Я решил поделитья ею, поскольку, как мне кажется, она представляет собой хороший практический пример решения проблем, возникающих в жизни проекта по разработке ПО.

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

Началось всё с того, что одна из команд разработчиков "дозрела" до применения такой полезной функции TFS как gated build для защиты репозитория от ломающих изменений. Это было сделано, но быстро выяснилось, что сборка занимала слишком много времени: один check-in занимал 15-20 минут, тогда как разработчикам хотелось бы, чтобы это происходило моментально. По результатам проведенного const/benefit analysis удалось договориться о том, что целевая длительность gated build - 5 минут.  Этого удалось достичь путем исключения интеграционных тестов из сборки, а также отказом от сборки инсталляционных пакетов, что в итоге дало время сборки ~4.5 минуты.

Но это было лишь началом. Спустя примерно два месяца от этой команды поступили жалобы на медленную сборку, которая вместо целевых пяти минут стала занимать около 20-25 минут. Поскольку наша сборочная инфраструктура виртуализирована, то было три уровня, на которых могли быть расположены причины деградации:
1. Исходный код и скрипты сборки, которые могли замедлиться в ходе развития;
2. Виртуальная машина сборочного сревера.
3. Виртуальная инфраструктура, поддерживавшая сборочный сервер, производительность которой могла деградировать по независящим от нас причинам.

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

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

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

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

Продолжение следует.