unity3d - 有没有办法在 Unity 中准确测量堆分配以进行单元测试?

标签 unity3d garbage-collection heap-memory

在 Unity 中的每一帧在堆上分配临时对象的成本很高,我们都尽力通过缓存堆对象和避免垃圾生成函数来避免这种情况。但是,什么时候会产生垃圾并不总是很明显。例如:

enum MyEnum {
  Zero,
  One,
  Two
}

List<MyEnum> MyList = new List<MyEnum>();
MyList.Contains(MyEnum.Zero); // Generates garbage

MyList.Contains() 生成垃圾,因为 List 的默认相等比较器使用 objects这会导致枚举值类型的装箱。

为了防止此类无意的堆分配,我希望能够在我的单元测试中检测到它们。

我认为这有两个要求:
  • 返回堆分配内存量的函数
  • 一种防止在测试过程中发生垃圾收集的方法

  • 我还没有找到一种干净的方法来确保#2。我为 #1 找到的最接近的东西是 GC.GetTotalMemory()
            [UnityTest]
            IEnumerator MyTest()
            {
              long before = GC.GetTotalMemory(false);
              const int numObjects = 1;
              for (int i = 0 ; i < numObjects; ++i)
              {
                System.Version v = new System.Version();
              }
              long after = GC.GetTotalMemory(false);
              Assert.That(before == after); 
            }
    

    问题是 GC.GetTotalMemory() 在此测试之前和之后返回相同的值。我怀疑 Unity/Mono 只从系统堆中分块分配内存,比如 4kb,所以你需要在 Unity/Mono 实际从系统堆中请求更多内存之前分配 <= 4kb,此时 GC.GetTotalMemory() 将返回不同的值。我确认,如果我将 numObjects 更改为 1000,GC.GetTotalMemory() 会在之前和之后返回不同的值。

    所以总而言之,1. 我怎样才能准确地获得堆分配的内存量,准确到字节和 2. 垃圾收集器能否在我的测试主体期间运行,如果是这样,是否有任何非 hacky 的方法来禁用 GC在我的测试期间

    TL; 博士
    谢谢你的帮助!

    最佳答案

    我在 Unity answers 上发布了同样的问题并得到了回复:

    https://answers.unity.com/questions/1535588/is-there-a-way-to-accurately-measure-heap-allocati.html

    不,基本上是不可能的。您可以在循环中多次运行单元测试,并希望它产生足够的垃圾来导致 GC.GetTotalMemory() 返回的值发生变化,但仅此而已。

    关于unity3d - 有没有办法在 Unity 中准确测量堆分配以进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51579982/

    相关文章:

    iphone - 在 iOS 中将 Unity 生成的代码与 Objective-C 混合?

    android - Activity 的第一个实例永远不会被垃圾收集?

    android - 我怎样才能强制Android垃圾收集旧的套接字信息?

    通过运行程序检查堆空间量;与实际边界不符

    c# - Unity3D 旋转未按预期运行

    c# - AOT 设备中的 Json.Net 反序列化是否需要空构造函数?

    c# - 条件检查后 Unity 中的协程功能异常

    garbage-collection - lua 垃圾收集器调试输出的最佳方式是什么?

    java - 函数的返回值不存储在任何变量中时是否占用内存?

    javascript - JavaScript 栈和堆的可视化