我想检测我的代码是否生成垃圾.所以我创建了以下单元测试.
[TestClass]
public class AllocationTest
{
int[] generationCollections = new int[3];
[TestMethod]
public void TestGarbageGeneration()
{
generationCollections[0] = GC.CollectionCount(0);
generationCollections[1] = GC.CollectionCount(1);
generationCollections[2] = GC.CollectionCount(2);
// Test for garbage here
for (int generation = 0; generation < generationCollections.Length; generation++)
{
Assert.AreEqual(GC.CollectionCount(generation), generationCollections[generation]);
}
}
}
我把代码置于“在这里测试垃圾”评论的位置,结果是不可预测的.我的理解是,这是因为GC在一个单独的线程上运行,并且可以在任何时候由我的测试以外的代码触发.
我尝试了GC.Collect在测试代码之前和之后强制运行集合,但后来意识到这总是会增加集合计数,因此测试总是失败.
有没有一种有意义的方法来测试单元测试中的垃圾?
最佳答案 您可以使用
WMemoryProfiler查找创建了多少其他类型.如果您对自己的流程进行概要分析,您将获得WMemoryProfiler用于生成报告的所有地址创建类型.
您可以通过使用单独的进程来监视您的managaed堆或仅限于您的类型.如果泄漏内存,您将在您创建的附加实例中看到它.
using (var dumper = new InProcessMemoryDumper(false,false))
{
var statOld = dumper.GetMemoryStatistics();
// allocaton code here
var diff = dumper.GetMemoryStatisticsDiff(statOld);
foreach (var diffinst in diff.Where(d => d.InstanceCountDiff > 1))
{
Console.WriteLine("Added {0} {1}", diffinst.TypeName, diffinst.InstanceCountDiff);
}
}
如果您追踪的是临时对象使用了多少内存,则需要使用一些分析Api或PerfView等工具,它们使用CLR生成的ETL跟踪.对于GC,您需要以编程方式启用像他这样的特定内容.我认为GCAllocationTick_V1赛事在你的情况下也很有意思.
如果你在尝试获取差异之前确实保留了对象的引用,那么你将很好地理解对象图将消耗多少内存.