Owe*_*ing 6 c# optimization compiler-optimization
我正在阅读提高.NET应用程序性能和可伸缩性.标题为避免重复字段或属性访问的部分包含一个准则:
如果在循环期间使用静态数据,请在循环之前获取它,而不是重复访问字段或属性.
以下代码作为示例给出:
for (int item = 0; item < Customer.Orders.Count; item++)
{
CalculateTax(Customer.State, Customer.Zip, Customer.Orders[item]);
}
Run Code Online (Sandbox Code Playgroud)
变
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]);
}
Run Code Online (Sandbox Code Playgroud)
文章指出:
请注意,如果这些是字段,编译器可能会自动执行此优化.如果它们是属性,则不太可能.如果属性是虚拟的,则无法自动完成.
为什么编译器以这种方式优化属性"更不可能",何时可以预期特定属性是否被优化?我假设在访问器中执行附加操作的属性对于编译器来说更难以优化,并且那些仅修改后备字段的属性更可能被优化,但是需要一些更具体的规则.自动实现的属性是否始终优化?
它需要抖动应用两个优化:
首先,属性 getter 方法必须内联,这样它就相当于字段访问。当 getter 很小并且不抛出异常时,这往往会起作用。这是必要的,以便优化器可以确保 getter 不依赖于可能受其他代码影响的状态。
请注意,如果 Customer.Orders[] 索引器会更改 Customer.State 属性,那么手动优化的代码将会出错。当然,像这样的惰性代码不太可能出现,但也不是从来没有这样做过:)优化器必须确定。
其次,必须将字段访问代码提升到循环体之外。称为“不变代码运动”的优化。当抖动可以证明循环体内的语句不会影响值时,适用于简单的属性获取器代码。
抖动优化器实现了它,但它并不出色。在这种特殊情况下,当它无法内联CalculateTax()方法时,它很可能会放弃。本机编译器会更积极地优化它,它可以消耗内存和分析时间。抖动优化器必须满足相当严格的期限以避免暂停。
当您自己执行此操作时,请务必牢记优化器的约束。当然,如果这些方法确实有你没有预料到的副作用,那就太丑陋了。仅当探查器告诉您此代码位于热路径上时才执行此操作,通常大约有 10% 的代码实际影响执行时间。这里的可能性很低,用于获取客户/订单数据的数据库查询将比计算税收贵几个数量级。幸运的是,像这样的代码转换也往往会使代码更具可读性,因此您通常可以免费获得它。YMMV。
有关抖动优化的背景知识请参见此处。
| 归档时间: |
|
| 查看次数: |
95 次 |
| 最近记录: |