Слишком много памяти используется во время автоматической сборки TFS
Мы используем TFS 2010 Standard Edition и настроили автоматическую сборку, которая запускается всякий раз, когда кто-то проверяет код. Мы выполняем все автоматизированные тесты (собранные с помощью MSTest) как часть сборки. Мы настроили сборку для запуска тестов как 64-битного процесса, но QTAgent.exe, который запускает тесты, увеличивается в памяти во время выполнения тестов. В настоящее время он достигает 8 ГБ для ~650 тестов, которые мы имеем, и процесс значительно замедлился, когда мы перешли с 450 тестов на 650 тестов.
Когда мы запускаем все тесты в локальной среде разработки, кажется, что память освобождается, по крайней мере, с каждым TestClass и никогда не превышает определенный уровень. Процесс запуска всех тестов существенно не увеличился в локальной среде разработки.
Есть ли способ настроить сервис сборки для освобождения памяти при каждом тестировании или каждом тестовом классе? При том, как все работает в настоящее время, процесс сборки становится очень медленным, когда мы начинаем исчерпывать память на машине.
Редактировать: я нашел вызов MSTest в журнале сборки, запустил его вручную и увидел то же самое поведение убегающей памяти. Я удалил параметры /publish, /publishbuild, /teamproject, /platform и /flavour из вызова MSTest на случай, если исполнитель теста удерживал результаты до конца, но поведение не изменилось. Я запустил одну и ту же командную строку в окне разработчика, отдельно от сервера сборки, и память часто освобождалась. Кажется, должно быть что-то не так / иначе с сервером сборки, который заставляет его вести себя по-другому, но я озадачен, где искать.
Я посмотрел на qtagent.exe.config, mstest.exe.config, версии обоих исполняемых файлов. Что еще может повлиять на это?
2 ответа
В конце концов я нашел причину, почему память использовалась так быстро во время автоматической сборки. Создав дамп QTAgent.exe, мы смогли изучить его содержимое, чтобы найти, что находится в куче.NET. Оказывается, мы помещали большое количество объектов в объект кеша, и, поскольку объект кеша живет для всего процесса, все эти объекты пережили сборку мусора.
Программная логика в наших тестах генерирует некоторые случайные данные, а затем проверяет, являются ли эти данные уникальными. По большей части, так и должно быть, но иногда происходит столкновение. Если происходит коллизия, мы заканчиваем кэшированием предыдущих данных. Это не должно быть проблемой, потому что наши тесты очищают свои данные после того, как они сделаны, и поэтому риск столкновения должен быть относительно низким.
Изучив то, что у нас есть в кеше, мы обнаружили, что мы столкнулись с множеством коллизий, и выясняется, что наша логика очистки не сработала только в среде автоматической сборки / тестирования из-за некоторых неправильно настроенных зависимостей. Это означает, что каждый раз, когда мы запускали наши тесты, мы генерировали больше данных, которые не были очищены, и последующие запуски рискуют загрузить эти данные в кэш на время выполнения теста.
Я признаю, что наличие тестов, которые не являются полностью изолированными, было частью нашей проблемы, но я хотел бы привести несколько других извлеченных уроков:
- Неверно, что тестовый агент будет удерживать результаты тестов таким образом, что это приведет к тому, что память выйдет из-под контроля, если при вызове MSTest из Visual Studio не произойдет того же самого.
- Полезно иметь возможность использовать такие инструменты, как WinDbg и анализ дампа, чтобы увидеть, что находится в памяти в вашем процессе.
Не совсем, проблема вызвана тем, что тестовый агент удерживает результаты всех тестов, чтобы в конце он мог обновить журнал. Я бы рекомендовал перейти от тестов Visual Studio к другому агенту тестирования (например, NUnit).
Это вызовет у вас некоторые головные боли, но в итоге вы должны найти более чистое решение.