因此,我的 Main()
方法中有以下代码
for (int x = 0; x < 100; x++) // to mimic BenchmarkDotnet runs
for (int y = 0; y < 10000; y++)
LogicUnderTest();
接下来我测试下面的类
[MemoryDiagnoser, ShortRunJob]
public class TestBenchmark
{
[Benchmark]
public void Test_1()
{
for (int i = 0; i < 10000; i++)
LogicUnderTest();
}
}
在 dotMemory
下运行 Main()
大约 6 分钟后,我收到以下结果
该应用从 10Mb
开始,一直到 14Mb
。
但是当我运行 BenchmarkDotnet
测试时,我得到了这个
我看到我已经分配了 2.6GB
。什么?好像一点都不好。此外,我看不到 Gen1
和 Gen2
列。这是否意味着代码没有在其中分配任何内容,因此没有任何内容可显示?
如何解释结果?在DotMemory
中似乎完全没问题,但在BenchmarkDotNet
中却不正常。我是 BenchmarkDotnet
的新手,对于有关结果的任何信息都会有所帮助。
附言。 LogicUnderTest()
广泛适用于字符串。
附言。大致来说,LogicUnderTest
是这样实现的
void LogicUnderTest()
{
var dict = new Dictionary<int, string>();
for (int j = 0; j < 1250; j++)
dict.Add(j, $"index_{j}");
string.Join(",", dict.Values);
}
最佳答案
我是MemoryDiagnoser
的作者,我还在我的blog 上提供了您问题的答案。 .我将在这里复制过去:
如何读取结果
| Method | Gen 0 | Allocated |
|----------- |------- |---------- |
| A | - | 0 B |
| B | 1 | 496 B |
- Allocated 包含分配的托管 内存的大小。 不包括 Stackalloc/ native 堆分配。它是每次调用,包含。
Gen X
列包含每 1 000 操作的Gen X
集合数。如果该值等于 1,则表示 GC 在X
代中每千次基准调用收集一次内存。 BenchmarkDotNet 在运行基准测试时使用了一些启发式方法,因此不同运行的调用次数可能不同。缩放使结果具有可比性。
Gen 列中的 -
表示未执行垃圾回收。- 如果
Gen X
列不存在,则意味着没有为X
代执行垃圾回收。如果您的基准测试均未引发 GC,则 Gen 列不存在。
阅读结果时请记住:
- 1 kB = 1 024 字节
- 每个引用类型实例都有两个额外的字段:对象头和方法表指针。这就是为什么结果总是包含每个对象分配的 2x 指针大小。有关额外开销的更多详细信息,请阅读这篇精彩的博客文章 How does Object.GetType() really work?康拉德·科科萨 (Konrad Kokosa) 着。
- CLR 做一些对齐。如果您尝试分配
new byte[7]
数组,它将分配byte[8]
数组。
关于c# - 如何解释 BenchmarkDotNet 和 dotMemory 的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52223682/