c# – 在单元测试中检测垃圾

我想检测我的代码是否生成垃圾.所以我创建了以下单元测试.

[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赛事在你的情况下也很有意思.

如果你在尝试获取差异之前确实保留了对象的引用,那么你将很好地理解对象图将消耗多少内存.

点赞