34 c# struct memory-management class-design
我阅读了Cwalina的书(关于.NET应用程序的开发和设计的建议).
他说,一个好的设计结构必须小于16个字节(出于性能目的).
这究竟是为什么?
而且(更重要的是)如果我在Windows 7 x64下在Core i7上运行我的.NET 3.5(很快将是.NET 4.0)64位应用程序(这是基于CPU/OS的限制),我可以拥有更高效率的结构吗?
只是再次强调 - 我需要尽可能高效的结构.我试着一直把它放在堆栈上.该应用程序是多线程的,并且以亚毫秒为间隔运行,结构的当前大小为64字节.
Ric*_*dOD 21
你错误地引用了这本书(至少是第2版).Jeffrey Richter声明值类型可以超过16个字节,如果:
您不打算将它们传递给其他方法或将它们复制到集合类中或从集合类中复制它们.
另外Eric Gunnerson补充说(关于16字节限制)
使用此指南作为触发器以进行更多调查.
结构"必须小于16个字节"是不正确的.这一切都取决于使用情况.
如果您正在创建结构并且也在使用它并且担心性能,那么使用分析器比较结构与类,以查看最适合您的结构.
sup*_*cat 10
JIT编译器生成特殊情况代码以复制小于某个阈值的结构,并为较大的结构生成稍微慢一些的通用构造.我猜想当写出这个建议时,阈值是16个字节,但在今天的32位框架中它似乎是24个字节; 对于64位代码,它可能更大.
话虽如此,创建任何大小类对象的成本远远大于复制保存相同数据的结构的成本.如果代码创建一个具有32字节字段的类对象,然后传递或以其他方式复制对该对象的引用1,000次,则复制1,000个对象引用而不必复制1,000个32字节结构所节省的时间可能会超过成本创建类对象.但是,如果在仅仅复制引用两次之后将放弃对象实例,则创建对象的成本可能会大大超过复制32字节结构两次的成本.
还要注意,在许多情况下,如果努力这样做,可以避免通过值传递结构或以其他方式冗余地复制它们.ref例如,将任何大小的结构作为参数传递给方法只需要传递单机字(4或8字节)地址.因为.net缺乏任何类型的const ref概念,只有可写字段或变量可以通过这种方式传递,而.net中构建的集合 - 除了 - System.Array提供无法访问成员ref.但是,如果有人愿意使用数组或自定义集合,则可以非常有效地处理大型(100字节或更多)结构.在许多情况下,使用结构而不是不可变类的性能优势可能随封装数据的大小而增长.
只有您知道结构在程序中的使用方式.但如果没有别的,你可以随时测试它.例如,如果它经常传递给其他功能,以下可能会照亮您:
class MainClass
{
    static void Main()
    {
        Struct64 s1 = new Struct64();
        Class64 c1 = new Class64();
        DoStuff(s1);
        DoStuff(c1);
        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < 10000; i++)
        {
            s1 = DoStuff(s1);
        }
        sw.Stop();
        Console.WriteLine("Struct {0}", sw.ElapsedTicks);
        sw.Reset();
        sw.Start();
        for (int i = 0; i < 10000; i++)
        {
            c1 = DoStuff(c1);
        }
        sw.Stop();
        Console.WriteLine("Class {0}", sw.ElapsedTicks);
        sw.Reset();
        Console.ReadLine();
    }
}
有:
public class Class64
{
    public long l1;
    public long l2;
    public long l3;
    public long l4;
    public long l5;
    public long l6;
    public long l7;
    public long l8;
}
public struct Struct64
{
    public long l1;
    public long l2;
    public long l3;
    public long l4;
    public long l5;
    public long l6;
    public long l7;
    public long l8;
}
尝试使用代表性结构/类的这种东西,看看你得到了什么结果.(在我的机器上,上面的测试,这个类似乎快3倍)
小智 5
较大的结构效率不高,但是......如果你有更多的数据,你就拥有了它。在那里谈论效率是没有意义的。
64字节应该没问题。
主要原因可能是复制操作......如果结构较大,复制操作会使 IIRC 变慢。而且它必须被大量复制。
我通常会建议在这里使用一个类;)但是如果不知道结构的内容,这就有点棘手。