5

我正在使用 BenchmarkDotNet 及其 MemoryDiagnoser 功能。

考虑以下基准:

[Benchmark]
public void Dummy()
{
   var buffer = new byte[1];
}

我希望它恰好分配 1 个字节。

但基准测试结果显示总共分配了 32 个字节。怎么来的?我觉得这很误导人。

| Method |     Mean |     Error |    StdDev |   Median | Ratio | Rank |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------- |---------:|----------:|----------:|---------:|------:|-----:|-------:|------:|------:|----------:|
|  Dummy | 4.486 ns | 0.1762 ns | 0.5196 ns | 4.650 ns |  1.00 |    1 | 0.0038 |     - |     - |      32 B |

                                                                                      why not 1 byte? ^^^^
4

3 回答 3

3

我是 MemoryDiagnoser 的作者,我已经描述了如何阅读我的博客的结果:https ://adamsitnik.com/the-new-Memory-Diagnoser/#how-to-read-the-results

CLR 会进行一些对齐。如果您尝试分配新的 byte[1] 数组,它将分配 byte[8] 数组。

我们需要额外的空间来存放对象头、方法表指针和数组长度。开销是 3x 指针大小。8 + 3x4 = 20 用于 32 位,8 + 3x8 = 32 用于 64 位。

于 2020-02-18T18:44:30.393 回答
0

我怀疑你在“/platform:x64”上。字节数组将占用“24 字节 + 长度”的空间,因为它的每个元素都是字节。此外,在 x64 上,所有大小都四舍五入到最接近的 8 个字节。

以下是测量尺寸的方法。

private void TestMemory(){
    long before = GC.GetTotalMemory(true);
    // Allocation code
    long after = GC.GetTotalMemory(true);
    double diff = after – before;
    Console.WriteLine(“Per object: “ + diff / size);
    // Stop the GC from messing up our measurements
    GC.KeepAlive(array);
}

至于你的问题,why?正如评论中提到的,它是这种高级语言的实现细节。

※因为内存对齐←我的回答中提到

※数组还包括一些元数据,例如它们的大小,以确保您不会索引到随机内存中。← 这可能与第一颗星有关

于 2020-02-16T14:34:32.877 回答
0

你没有分配一个字节。您正在分配一个字节数组。Array 是一种引用类型,所有引用类型的实例都有一些开销所以任何数组的总大小都大于元素的大小。亚当的回答很好地分解了细节。

于 2020-02-18T18:50:30.097 回答