我正在使用Red Gate的Performance Profiler优化物理模拟程序。处理碰撞检测的代码的一部分有大约52个以下的小检查,在两个案例中处理3维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);
作为程序的一个非常紧凑的循环,所有这一切都必须采用相同的方法,但是在我将区域从两个维度扩展到三维之后,我突然发现了这一点(将计数从上升到52个16),突然cell.Count不再被内联,即使它是一个简单的吸气剂。
public int Count { get { return count; } }
这引起了巨大的性能损失,我花了相当长的时间才发现,当cell.Count出现在方法中28次或更少时,它每次都被内联,但一旦cell.Count出现在方法中29次或更多次,它没有一次内联(尽管绝大多数调用都是来自极少情况的代码部分很少被执行。)
回到我的问题,是否有人有任何想法绕过这个限制?我认为简单的解决方案只是使计数字段内部而非私密,但我想要一个比这更好的解决方案,或者至少只是更好地了解情况。我希望微软在http://msdn.microsoft.com/en-us/library/ms973858.aspx编写高性能管理应用程序页面上会提到这类事情,但遗憾的是它不是(可能是因为28计数限制有多么武断?)
我使用的是.NET 4.0。
编辑:看起来我误解了我的小测试。我发现内联失败不是因为方法本身被调用了28次以上,而是因为它们应该被内联到的方法被一些标准“太长”了。这仍然让我感到困惑,因为我没有看到一个简单的getter如何理性地没有内联(并且我的分析器清楚地向我显示了内联的性能明显更好),但显然CLI JIT编译器拒绝内联任何东西只是因为这个方法已经很大了(玩了一些细微的变化表明我这个限制是1500的代码大小(来自idasm),超过这个限制没有内联,即使在我的getter的情况下,一些测试显示没有添加额外的代码要内联的开销。)谢谢。
答案 0 :(得分:4)
我还没有对此进行过测试,但似乎有一种可能的解决方法是让多个属性都返回相同的东西。可以想象,每个属性可以获得28个内联。
请注意,内联方法的次数很可能取决于该方法的本机代码的大小(请参阅http://blogs.msdn.com/b/vancem/archive/2008/08/19/to-inline-or-not-to-inline-that-is-the-question.aspx),数字28特定于该属性。一个简单的属性可能比一个更复杂的方法内联更多次。
答案 1 :(得分:1)
直接关闭,这并不能解释为什么28是神奇数字,但我很好奇如果你将所有候选CollisionListPrimitive实例整理成一个数组,然后调用你的“if count> 0”块会发生什么在数组的循环中?
然后,cell.Count调用再次内联吗?
e.g。
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);
}
我知道性能是问题,你将有构建数组和循环的开销,但如果cell.Count再次内联,那么整体性能是否仍然更好/更好?
答案 2 :(得分:0)
我猜测(虽然绝不是积极的)这可能与提到的enregistration问题有关 - CLR可能为每个if语句分配一个新变量,而那些是超过总共64个变量。你认为情况可能如此吗?