几个月前我参加了一个研讨会,演讲者发表声明说,自 .NET 1.1 以来,装箱或拆箱操作的一般成本已经降低。我查看了我的(糟糕的)笔记,无法确定该语句是否引用了装箱和拆箱指令,或者是引入了使装箱/拆箱不太可能发生的类(即泛型类型)。
.NET 1.1 和 .NET 4.0 之间的 CLR 装箱相关指令是否有性能改进,如果是,我在哪里可以找到显示收益的测量信息?
我无法评论性能(因为你需要分析等) - 但这里的一个有趣的变化是受约束的操作码,特别是与泛型一起使用。这里的优点是对于像这样的方法:
static void DoSomething<T>(T x, T y) where T : IComparable<T>
{
if(x.CompareTo(y) < 0) { /* whatever */ }
}
它将使用约束调用CompareTo
,这允许它对值类型(没有取消框)的方法实现使用静态调用,或者如果它是引用类型,则使用虚拟调用。通常,在值类型上调用基于接口的方法需要一个框,所以这非常有用。
应尽可能避免装箱和拆箱。来自MSDN:
最好避免在必须多次装箱的情况下使用值类型,例如在 System.Collections::ArrayList 等非泛型集合类中。您可以通过使用诸如 System.Collections.Generic::List 之类的泛型集合来避免值类型的装箱。装箱和拆箱是计算成本高的过程。当一个值类型被装箱时,必须创建一个全新的对象。与简单的参考分配相比,这可能需要长达 20 倍的时间。拆箱时,铸造过程可能需要四倍于作业的时间。
MS 已尽其所能将拳击操作本身的成本降至最低,但能做的只有这么多。
通过从代码中消除尽可能多的装箱,可以实现更好的性能改进。避免使用非通用容器是大规模减少装箱的一种非常有效的方法。能够使用通用容器是从 NETFX 1.1 迁移到 2.0+ 的主要好处之一。