Eu finalmente encontrei a razão pela qual a memória estava sendo consumida tão rapidamente durante a construção automatizada. Criando um despejo de QTAgent.exe, pudemos examinar seu conteúdo para encontrar o que está no heap .NET. Acontece que estávamos colocando um grande número de objetos em um objeto de cache e, como o objeto de cache vive para todo o processo, todos esses objetos estavam sobrevivendo à coleta de lixo.
A lógica do programa em nossos testes gera alguns dados aleatórios e, em seguida, verifica se esses dados são exclusivos. Na maior parte, deveria ser, mas ocasionalmente há uma colisão. Se houver uma colisão, acabamos armazenando em cache os dados anteriores. Isso não deve ser um problema porque nossos testes limpam seus dados depois que eles são feitos e, portanto, o risco de colisão deve ser relativamente baixo.
Examinando o que temos no cache, descobrimos que deveríamos estar colidindo com muitas colisões, e descobrimos que nossa lógica de limpeza estava falhando apenas no ambiente de criação / teste automatizado, devido a algumas configurações incorretas dependências. Isso significa que toda vez que executamos nossos testes, geramos mais dados que não estavam sendo limpos, e as execuções subseqüentes correriam o risco de carregar esses dados no cache durante a execução do teste.
Eu reconheço que ter testes que não são completamente isolados fazia parte do nosso problema, mas eu gostaria de chamar algumas outras lições aprendidas:
- Não é verdade que o Agente de teste manterá os resultados dos testes de forma que a memória fique fora de controle quando a mesma coisa não estiver acontecendo ao chamar o MSTest do Visual Studio.
- É útil poder usar ferramentas como o WinDbg e a análise de dump para ver o que está na memória em seu processo.