c# – 在循环期间保持静态的属性的编译器优化

前端之家收集整理的这篇文章主要介绍了c# – 在循环期间保持静态的属性的编译器优化前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在阅读 Improving .NET Application Performance and Scalability.标题为避免重复字段或属性访问的部分包含一个准则:

If you use data that is static for the duration of the loop,obtain it
before the loop instead of repeatedly accessing a field or property.

以下代码作为示例给出:

for (int item = 0; item < Customer.Orders.Count; item++)
{
   CalculateTax(Customer.State,Customer.Zip,Customer.Orders[item]);
}

string state = Customer.State;
string zip = Customer.Zip;
int count = Customers.Orders.Count;
for (int item = 0; item < count; item++)
{
   CalculateTax(state,zip,Customer.Orders[item]);
}

文章指出:

Note that if these are fields,it may be possible for the compiler to
do this optimization automatically. If they are properties,it is much
less likely. If the properties are virtual,it cannot be done
automatically.

为什么编译器以这种方式优化属性“更不可能”,何时可以预期特定属性是否被优化?我假设在访问器中执行附加操作的属性对于编译器来说更难以优化,并且那些仅修改后备字段的属性更可能被优化,但是需要一些更具体的规则.自动实现的属性是否始终优化?

解决方法

它需要抖动应用两个优化:

首先,必须内联属性getter方法,使其变为等效的字段访问.当getter很小并且不会抛出异常时,这往往会起作用.这是必要的,因此优化器可以确保getter不依赖于可能受其他代码影响的状态.

请注意,如果Customer.Orders []索引器改变Customer.State属性,那么手动优化代码将是错误的.像这样的懒惰代码当然不太可能,但它从未像现在这样做过:)优化器必须确定.

其次,必须从循环体中提升现场访问代码.一种称为“不变代码运动”的优化.当抖动可以证明循环体内的语句不影响值时,可以使用简单的属性getter代码.

抖动优化器实现了它,但它并不是很好.在这种特殊情况下,当它无法内联CalculateTax()方法时,它很可能会放弃.本机编译器可以更加积极地优化它,它可以在内存上刻录内存和分析时间.抖动优化器必须满足相当困难的最后期限才能避免暂停.

当你自己这样做时,请记住优化器的约束.当然,如果这些方法确实存在您没有依赖的副作用,那就是相当难看的丑陋bug.只有当分析器告诉你这段代码在热门路径上时才会这样做,典型的~10%的代码实际上会影响执行时间.这里的概率很低,用于获取客户/订单数据的dbase查询比计算税收要贵几个数量级.幸运的是,像这样的代码转换也会使代码更具可读性,因此您通常可以免费获得代码.因人而异.

关于抖动优化的背景资料is here.

猜你在找的C#相关文章