为什么分配的内存比预期的多?

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? ^^^^

2
可能是由于内存对齐的原因?这可能会加快进程。 - Jeroen van Langen
1
数组还包括一些元数据,比如它们的大小,以确保您不会索引到随机内存。 - juharr
@JeroenvanLangen,您能否更详细地解释一下内存对齐和优化的问题? - silkfire
1
@silkfire LMGTFY:这是一份关于C++的文档,但同样适用于任何其他编程语言:对齐 - Jeroen van Langen
3个回答

4

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

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

我们需要额外的空间用于对象头、方法表指针和数组的长度。开销为3x Pointer Size。32位系统下,8 + 3x4 = 20;64位系统下,8 + 3x8 = 32。


0

你没有分配一个字节,而是分配了一个字节数组。数组是引用类型,所有引用类型实例都带有一些开销。因此,任何数组的总大小都比元素的大小大。Adam的答案详细解释了这些细节。


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);
}

关于你的问题,为什么?正如评论中所提到的,这是高级语言的实现细节。
※由于内存对齐的原因← 如我所答复提及。
※此外,数组包括一些元数据,例如它们的大小,以确保你不会超出随机内存的索引。← 这可能与第一个星号有关。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接