为什么编译器不优化这段代码
Why isn't compiler optimizing away this code
我有一个使用第三方工具迭代点集合的代码。
for (int i = 0; i < pcoll.PointCount; i++) { /* ... */ }
通过 dotTrace 进行分析时,我注意到 PointCount
-proerty 每次迭代都会被访问(见上图)
.
我预计此 属性 的值会被编译器优化掉,但显然这并没有发生。也许这实际上是基于 COM 的第 3 方库中的问题,或者在收集信息时也是 dotTrace self 中的问题。
我不确定这个话题是否更适合 Gis.StackExchange。然而,也许有人知道在什么情况下不会进行优化或如何进行优化。
简单地说,编译器如何知道 pcoll.PointCount
是否会在调用之间发生变化?它不能安全地假设该值将保持不变,因此它不能通过缓存第一次调用 pcoll.PointCount
的值来优化此代码。
它可能在此期间发生了变化。
确实,每次迭代都测试 i < pcoll.PointCount
而不是仅使用 foreach(var point in pcoll)
的原因之一正是因为 you 认为集合可能会在同时,枚举器不保证应对他们枚举的集合的变化。
例如,这不同于通过局部变量访问的数组,因为通过局部变量访问的数组的 Length
可以更改的唯一方法是在本地进行更改。
尽管如此,还是值得记住编译器经常会跳过一些明显的优化,因为众所周知抖动也会进行相同的优化。
字段 的预期优化是正确的。但是 属性 有 setter/getter(访问 属性 实际上是将它们作为方法调用),因此编译器将很难尝试优化它。
要修复,将其设为字段或读取一次
var max = pcoll.PointCount;
for (int i = 0; i < max; i++) { /* ... */ }
我有一个使用第三方工具迭代点集合的代码。
for (int i = 0; i < pcoll.PointCount; i++) { /* ... */ }
通过 dotTrace 进行分析时,我注意到 PointCount
-proerty 每次迭代都会被访问(见上图)
我预计此 属性 的值会被编译器优化掉,但显然这并没有发生。也许这实际上是基于 COM 的第 3 方库中的问题,或者在收集信息时也是 dotTrace self 中的问题。
我不确定这个话题是否更适合 Gis.StackExchange。然而,也许有人知道在什么情况下不会进行优化或如何进行优化。
简单地说,编译器如何知道 pcoll.PointCount
是否会在调用之间发生变化?它不能安全地假设该值将保持不变,因此它不能通过缓存第一次调用 pcoll.PointCount
的值来优化此代码。
它可能在此期间发生了变化。
确实,每次迭代都测试 i < pcoll.PointCount
而不是仅使用 foreach(var point in pcoll)
的原因之一正是因为 you 认为集合可能会在同时,枚举器不保证应对他们枚举的集合的变化。
例如,这不同于通过局部变量访问的数组,因为通过局部变量访问的数组的 Length
可以更改的唯一方法是在本地进行更改。
尽管如此,还是值得记住编译器经常会跳过一些明显的优化,因为众所周知抖动也会进行相同的优化。
字段 的预期优化是正确的。但是 属性 有 setter/getter(访问 属性 实际上是将它们作为方法调用),因此编译器将很难尝试优化它。
要修复,将其设为字段或读取一次
var max = pcoll.PointCount;
for (int i = 0; i < max; i++) { /* ... */ }