是否有解决c# 28次内联限制的方法?

本文关键字:方法 解决 28次 是否 | 更新日期: 2023-09-27 17:53:02

我正在使用Red Gate的性能分析器优化物理模拟程序。处理碰撞检测的代码的一部分有大约52个以下小检查,处理三维26个方向的细胞,在两种情况下。

CollisionPrimitiveList cell = innerGrid[cellIndex + 1];
if (cell.Count > 0)
    contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);
cell = innerGrid[cellIndex + grid.XExtent];
if (cell.Count > 0)
    contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);
cell = innerGrid[cellIndex + grid.XzLayerSize];
if (cell.Count > 0)
    contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);

作为程序的一个非常紧密的循环,所有这些都必须在相同的方法中,但是我发现,突然,当我将面积从二维扩展到三维(将计数从16次增加到52次)时,突然出现了cell。Count不再被内联,尽管它是一个简单的getter。public int Count { get { return count; } }这对性能造成了巨大的影响,我花了很长时间才发现这一点。计数在方法中出现28次或更少,每次内联,但一次细胞。Count在方法中出现了29次或更多次,它没有被内联一次(即使绝大多数调用来自很少执行的最坏情况的代码部分)

回到我的问题,有人知道如何绕过这个限制吗?我认为简单的解决方案就是使count字段内部而不是私有,但我想要一个比这更好的解决方案,或者至少只是更好地理解这种情况。我希望这类事情会在微软的编写高性能托管应用程序页面上提到http://msdn.microsoft.com/en-us/library/ms973858.aspx,但遗憾的是它没有(可能是因为28计数限制是多么随意?)

我正在使用。net 4.0。

编辑:看起来我误解了我的小测试。我发现内联失败不是因为方法本身被调用了28次以上,而是因为按照某种标准,它们应该内联到的方法"太长"了。这仍然让我感到困惑,因为我不明白如何合理地不内联一个简单的getter(并且性能显着更好,因为它们内联我的分析器清楚地告诉我),但显然CLI JIT编译器拒绝内联任何东西,只是因为方法已经很大(玩一些轻微的变化告诉我,这个限制是1500的代码大小(来自idasm),超过这个限制没有内联,即使在我的getter的情况下,一些测试显示没有增加额外的代码开销来内联)。

谢谢。

是否有解决c# 28次内联限制的方法?

我还没有测试过这个,但似乎有一个可能的解决方案是有多个属性,所有返回相同的东西。可以想象,你可以得到每个属性28行。

请注意,方法内联的次数很可能取决于该方法的本机代码的大小(参见http://blogs.msdn.com/b/vancem/archive/2008/08/19/to-inline-or-not-to-inline-that-is-the-question.aspx),数字28是特定于该属性的。一个简单的属性可能会比一个更复杂的方法内联更多次。

直截了当地说,这并不能解释为什么28是一个神奇的数字,但我很好奇,如果你把所有候选CollisionListPrimitive实例整理成一个数组,然后在数组的循环中调用你的"if count> 0"块,会发生什么?

是单元格。计数调用然后再次内联?

CollisionPrimitiveList[] cells = new CollisionPrimitiveList {
    innerGrid[cellIndex + 1],
    innerGrid[cellIndex + grid.XExtent],
    innerGrid[cellIndex + grid.XzLayerSize]
    // and all the rest
};
// Loop over cells - for demo only. Use for loop or LINQ'ify if faster
foreach (CollisionPrimitiveList cell in cells) 
{
    if (cell.Count > 0)
        contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);  
}

我知道性能是一个问题,你会有开销构造数组和循环它,但如果单元格。计数再次内联,性能是否仍然更好/足够好?

我猜测(虽然不是肯定的)这可能与提到的注册问题有关——CLR可能为每个if语句分配一个新变量,并且这些变量总数超过64个。你认为情况可能是这样吗?