为什么应该一个.NET结构less于16个字节?
我现在读了几个地方,一个结构的最大实例大小应该是16个字节。
但我看不出这个数字(16)来自哪里。
浏览networking,我发现一些人认为这是一个好的performance,但微软说这是一个艰难的上限。 (如MSDN )
有没有人有一个明确的答案,为什么它是16字节?
这只是一个性能规则。
重点在于,因为值types是通过值传递的,所以如果结构体的全部大小被传递给一个函数,那么它的整个大小就必须被复制,而对于一个引用types,只有引用(4字节)必须被复制。 结构可能会节省一点时间,因为你删除了一个间接层,所以即使它大于这4个字节,也可能比传递一个引用更有效率。 但是,从某种程度来说,复制的成本变得如此之大,变得明显。 一个常见的经验法则是,这通常发生在16个字节左右。 select16是因为它是一个很好的整数,2的幂,而且可选项是8(它太小了,会使结构几乎无用),或32(在这一点上复制结构的代价已经成问题了如果您出于性能原因使用结构)
但最终,这是绩效build议。 它回答了“哪一个最有效的使用结构或类?”的问题。 但是它并没有回答“哪个地图最适合我的问题”。
结构和类的行为有所不同。 如果你需要一个结构的行为,那么无论大小如何,我都会说它是一个结构。 至less在遇到性能问题之前,请分析您的代码,并发现您的结构是一个问题。
你的链接甚至说,这只是一个performance的问题:
如果一个或多个这些条件不符合,创build一个引用types,而不是一个结构。 不遵守这一准则会对性能产生负面影响。
如果一个结构不超过16个字节,可以用一些简单的处理器指令来复制。 如果更大,则使用循环来复制结构。
只要结构不超过16个字节,复制结构的时候处理器就必须完成与复制参考文件相同的工作。 如果结构较大,则失去了结构的性能优势,一般应该把它变成一个类。
大小的数字主要来自复制栈上的结构所需的时间,例如传递给一个方法。 任何比这更大的东西,你正在消耗大量的堆栈空间和CPU周期只是复制数据 – 当一个不可变类的引用(即使取消引用)可以更有效。
正如其他答案所指出的那样,复制大于特定阈值的结构(在.NET的早期版本中为16字节,但已经增长到20-24)的每字节成本显着大于每个字节的成本,字节成本较小的结构。 然而,重要的是要注意,复制任何特定大小的结构一次将会是创build相同大小的新类对象实例的一小部分成本。 如果一个结构在其生命周期中被复制了很多次,并且值types的语义并不是特别必要的,那么类对象可能是优选的。 但是,如果一个结构最终会被复制一次或两次,那么这样的复制可能会比创build一个新的类对象便宜。 类对象将变得更便宜的副本的数量的收支平衡副本根据所讨论的结构/对象的大小而变化,但是对于低于“廉价复制”阈值的事情而言,要比上述事情要高得多。
顺便说一句,值得一提的另一点是,作为ref
parameter passing结构的代价是独立的结构的大小。 在许多情况下,可以通过使用值types并通过ref
传递来实现最佳性能。 一旦必须小心避免使用结构types的属性或readonly
字段,因为访问其中的任何一个都将创build所述结构的隐式临时副本。
这是一个结构可以performance出卓越性能的场景:
当你需要创build1000个实例时。 在这种情况下,如果您要使用类,则首先需要分配数组来保存1000个实例,然后在循环中分配每个实例。 但相反,如果你要使用结构,那么在分配要保存它们的数组之后,数千个实例将立即变为可用。
此外,当您需要执行互操作或因性能原因而陷入不安全的代码时,结构非常有用。
一如既往,有一个权衡,需要分析他们正在做什么来确定最佳的实现方式。
ps:当我使用激光雷达数据时,这种情况开始发挥作用,其中可能有数百万个点代表地面数据的x,y,z和其他属性。 这些数据需要加载到内存中进行一些密集计算才能输出各种东西。
从性能的angular度来看,我认为16字节只是一个经验法则。 .NET中的一个对象至less使用了24个字节的内存(IIRC),所以如果你的结构比这个大得多,那么引用types会更好。
我想不出为什么他们特意select了16个字节。