C#原始类型别名的结构开销是多少?

3
我注意到C#中的原始类型实际上只是在System命名空间中定义的结构体的别名,例如ulongSystem.UInt64的别名,它是struct类型。由此产生的C#原始类型是否存在任何额外的空间和时间开销?比如说ulong真的只占用8个字节的内存吗?
从本质上讲,这应该测试内存开销:
using System;

class Program
{
    static void Main()
    {
        long beforeAlloc = GC.GetTotalMemory(false);
        ulong[] myArray = new ulong[System.Int32.MaxValue];
        myArray[0] = 1;
        long afterAlloc = GC.GetTotalMemory(false);

        Console.WriteLine(((afterAlloc - beforeAlloc) / System.Int32.MaxValue).ToString());
     }
}

但是文档明确指出,GC.GetTotalMemory()方法仅检索当前被认为已分配的字节数,所以没有更复杂的内存分析器,是否有简单的方法来查找呢?


2
不,没有额外的开销。 - Lee
1
你认为为什么会有额外开销? - jamesSampica
2个回答

3

结构体本身没有开销。然而,运行时可以通过填充任何复合类型来进行对齐优化。

有关运行时如何处理数组的详细信息,请参见此问题


谢谢!我有两个后续问题,(1)除了GC.GetTotalMemory()之外,是否有更快但更可靠的方法来测试这个假设?(2-与主要问题无关)由于运行时填充复合类型,是否重新排列结构成员从大到小的大小类似于C标准有优势? - elleciel
1
这取决于你想要什么。请记住,CLR代表您的应用程序作为内存管理器,因此它将在操作系统级别上分配和释放内存。这里真正的问题可能是你想知道为什么? - Brian Rasmussen
只是出于好奇。我在C语言中尝试了不同地址空间上分配的结构体的位置,并决定看看其他编程语言,结果发现了C#中的这个奇怪规范。我猜这是一个很好的技巧,通过重新排列结构体成员来判断是否可以将结构体压缩到1或2个缓存行中。 :) - elleciel
@BrianRasmussen,一个只包含单个 int 的结构体是否比单独的 int 有更多开销?即 Struct MyInt { int a; } vs int a; - lozzajp

1
原始类型由编译器进行别名处理。无论您使用还是,生成的代码没有区别。在您的示例中,和都是结构体;它们都继承自System.ValueType。这是因为它们实际上是相同的类型。
然而,如果您使用关键字,编译器会稍微快一点。例如,当您使用时,编译器会从所有其他作用域中解析类型名称,注意命名空间和指令,以确定该类型不是其他某个其他人编写的类型。别名不会发生这种情况。
如果您能找到一个实际上可以测量到这种差异的示例,我会非常惊讶!

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