【发布时间】:2015-05-20 17:19:20
【问题描述】:
我在 C# 中发现了一个奇怪的东西。我有一个类 A,只包含一个对 A 的引用。然后我在 for 循环内的每次迭代中创建新对象 A,并引用在前一次迭代中创建的对象。但是如果我更改对 for 循环之前创建的对象的引用,它会快得多。为什么会这样?
class A
{
private A next;
public A(A next)
{
this.next = next;
}
}
var a = new A(null);
for (int i = 0; i < 10*1000*1000; i++)
a = new A(a);
// Takes 1.5s
var b = new A(null);
for (int i = 0; i < 10*1000*1000; i++)
a = new A(b);
// Takes only 0.17s
我在以通常方式实现不可变堆栈的过程中发现了这一点,并通过VList 发现了这一点,这是因为速度要快得多。
【问题讨论】:
-
猜测是因为在第二种情况下,每次调用
a = new A(b)时,对旧A实例的引用都会丢失,因此CLI 可以重用其内存。在第一种情况下,必须分配额外的内存来保存您创建的 1000 万个实例,同时保留对所有实例的引用。 -
小提示,但在进行此类计时测试时,总是对数据进行某种基本的完整性/正确性检查,尤其是当您看到如此天文数字的计时结果时。您不想对快速但不正确的解决方案感到太兴奋。正如他们所说,以两倍速度给出错误结果的东西会无限慢。
标签: c# .net performance jit