Назад | Перейти на главную страницу

Слишком много памяти потребляется во время автоматической сборки TFS

Мы используем TFS 2010 Standard Edition, и мы настроили автоматическую сборку для запуска всякий раз, когда кто-то проверяет код. Мы запускаем все автоматизированные тесты (построенные с помощью MSTest) как часть сборки. Мы настроили сборку для запуска тестов как 64-битный процесс, но QTAgent.exe, который запускает тесты, увеличивается в памяти во время выполнения тестов. В настоящее время он достигает 8 ГБ для ~ 650 тестов, которые у нас есть, и процесс значительно замедлился, когда мы перешли с 450 тестов на 650.

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

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

Изменить: я нашел вызов MSTest в журнале сборки, запустил его вручную и увидел такое же поведение неуправляемой памяти. Я удалил параметры / publish, / publishbuild, / teamproject, / platform и / flame из вызова MSTest на тот случай, если средство выполнения тестов сохраняло результаты до конца, но поведение не изменилось. Я запускал ту же командную строку в окне разработчика, отдельно от сервера сборки, и память часто освобождалась. Кажется, что что-то не так / отличается от сервера сборки, из-за которого он ведет себя иначе, но я не понимаю, где искать.

Я просмотрел qtagent.exe.config, mstest.exe.config, версии обоих исполняемых файлов. Что еще может на это повлиять?

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

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

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

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

  • Неверно, что агент тестирования будет удерживать результаты тестов таким образом, чтобы память вышла из-под контроля, когда то же самое не происходит при вызове MSTest из Visual Studio.
  • Полезно иметь возможность использовать такие инструменты, как WinDbg и анализ дампа, чтобы увидеть, что находится в памяти вашего процесса.

Не совсем, проблема вызвана тем, что агент тестирования хранит результаты всех тестов, поэтому он может обновить журнал в конце. Я бы рекомендовал перейти от тестов Visual Studio к другому агенту тестирования (например, NUnit).

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