我们正在运行 TFS 2010 标准版,并且我们已设置自动构建,以便在有人签入代码时运行。我们将所有自动测试(使用 MSTest 构建)作为构建的一部分运行。我们已将构建配置为以 64 位进程运行测试,但运行测试的 QTAgent.exe 在测试运行时占用的内存会增长。目前,对于我们拥有的 ~650 个测试,内存已达到 8GB,而当我们从 450 个测试增加到 650 个测试时,该进程明显变慢。
当我们在本地开发环境中运行所有测试时,内存似乎至少会随着每个 TestClass 释放,并且永远不会超过某个水平。在本地开发环境中运行所有测试的过程并没有显着增加。
有没有办法配置构建服务以释放每个测试或每个测试类的内存?按照目前的运行方式,当我们开始耗尽机器内存时,构建过程会变得非常缓慢。
编辑:我在构建日志中找到了 MSTest 调用并手动运行它,看到了相同的内存失控行为。我从 MSTest 调用中删除了 /publish、/publishbuild、/teamproject、/platform 和 /flavor 参数,以防测试运行器一直保留结果直到最后,但行为没有改变。我在与构建服务器分开的开发框上运行了相同的命令行,内存经常被释放。似乎构建服务器一定有什么问题/不同之处导致它的行为不同,但我不知道该去哪里找。
我查看了 qtagent.exe.config、mstest.exe.config 这两个可执行文件的版本。还有什么可能影响此情况?
答案1
我最终找到了自动构建过程中内存消耗如此之快的原因。通过创建 QTAgent.exe 的转储,我们能够检查其内容以查找 .NET 堆上的内容。事实证明,我们将大量对象放入缓存对象中,并且由于缓存对象在整个过程中都存在,因此所有这些对象都在垃圾收集中幸存下来。
我们测试中的程序逻辑会生成一些随机数据,然后检查这些数据是否唯一。大多数情况下,数据应该是唯一的,但偶尔也会有冲突。如果发生冲突,我们最终会缓存以前的数据。这应该不是问题,因为我们的测试完成后会清理数据,因此发生冲突的风险应该相对较低。
通过检查缓存中的内容,我们发现我们一定遇到了很多冲突,事实证明,由于一些配置不当的依赖项,我们的清理逻辑仅在自动构建/测试环境中失败。这意味着每次运行测试时,我们都会生成更多未清理的数据,并且后续运行将面临在测试运行期间将这些数据加载到缓存中的风险。
我认识到,测试不完全隔离是我们的问题的一部分,但我想指出其他一些经验教训:
- 测试代理会以某种方式保留测试结果,从而导致内存失控增长,但从 Visual Studio 调用 MSTest 时不会发生同样的事情,这是不正确的。
- 能够使用 WinDbg 和转储分析等工具查看进程内存中的内容很有用。
答案2
不是,问题是由测试代理保存所有测试的结果,以便最后更新日志引起的。我的建议是从 Visual Studio 测试转移到另一个测试代理(如 NUnit)。
这会给你带来一些麻烦,但最终你会得到一个更清洁的解决方案。