0

想知道是否有人可以解释我们的绘图代码中这个奇怪的小优化是怎么回事。我们用第二个代码替换了第一个小代码,并获得了巨大的速度提升(4400 滴答声 -> 15 个滴答声,使用秒表类)

// Add all the visible sprites to the list
m_renderOrder.Clear();
foreach (CSpriteInternalData sprite in m_InternalData)
{
    if (!sprite.m_bRender) continue;
    m_renderOrder.Add(sprite);
}

换成...

// Add all the visible sprites to the list
m_renderOrder.Clear();
renderOrderCount = 0;
for (int i = 0; i < m_numSprites; i++ )
{
    if (m_InternalData[i].m_bRender)
        m_renderOrder[renderOrderCount++] = m_InternalData[i];
}

我看起来是最简单的小改动,对于速度的如此巨大的提升。任何人都可以帮忙吗?

4

3 回答 3

3

如果CSpriteInternalData是 a struct,即值类型,则每次将该类型的值分配给变量时,都会完成一个副本。

MyStruct a = new MyStruct(50);
MyStruct b = a; //a is copied to b;
a.Value = 10;
Console.WriteLine(b.Value); //still 10, has a separate copy of value

如果结构体小且可移植,这不是什么大问题,但如果结构体很大,它们可能会变慢。Foreach创建一个从集合中重复分配值的变量,因此如果CSpriteInternalData是 a struct,则每个变量依次复制到sprite变量中,这可能需要一些时间。

此外,当您Add将项目添加到m_renderOrder集合时,该行会调用结构的另一个副本,但我猜其中只有少数m_bRender设置了标志,因此不会花费太多时间。

如果这是减速/加速的原因,我会全心全意地建议您更改CSpriteInternalData为使用引用行为的类,并且只复制引用,而不是整个副本。

于 2012-10-05T08:49:00.733 回答
0

foreach 始终创建由 GetEnumerator 方法返回的枚举器的实例,并且该枚举器还在 foreach 循环的整个生命周期中保持状态。然后它反复调用枚举器上的 Next() 对象,并为它返回的每个对象运行您的代码。

您可以创建自己的模拟器以防万一。但是当执行时间很重要时,最好使用 for 循环。

于 2012-10-05T08:45:55.660 回答
0

foreach 循环的目的略有不同。它用于迭代一些实现 IEnumerable 的集合。它的性能要慢得多。

供您参考

http://www.codeproject.com/Articles/6759/FOREACH-Vs-FOR-C

于 2012-10-05T08:54:35.707 回答