【问题标题】:Why isn't compiler optimizing away this code为什么编译器不优化此代码
【发布时间】:2015-09-15 19:58:13
【问题描述】:

我有一个使用第三方工具迭代点集合的代码。

for (int i = 0; i < pcoll.PointCount; i++) { /* ... */ }

通过 dotTrace 进行分析时,我注意到每次迭代都会访问 PointCount-proerty(见上图)

.

我预计该属性的值会被编译器优化掉,但显然这不会发生。也许这实际上是基于 COM 的 3rd-party 库中的一个问题,或者在收集信息时也出现在 dotTrace self 中。

我不确定这个主题是否更适合 Gis.StackExchange。但是,也许有人知道在哪些情况下不会进行优化或如何进行优化。

【问题讨论】:

  • 我不肯定,但我认为这与属性有关,是 C# 中的方法。所以它可能无法静态知道pcoll.PointCount EDIT 的值。查看调用 get 方法时发生的堆栈跟踪。除非它们可以内联,否则您无法优化它们。
  • int pointCount = pcoll.PointCount; for (int i = 0; i &lt; pointCount ; i++) { /*.. */ } 现在被缓存,属性只被访问一次。
  • @TomDDD 内联是较小的一点 - 较大的一点是编译器无法知道存储 PointCount 的值是否安全,因为只有当 pcoll 是不可变的时才有可能,并且 @ 987654328@ 是纯的 - 编译器无法知道这一点。通常,编译器会忽略第一点(也就是说,它们会忽略跨线程访问——在同一个线程中访问它也可能会阻止“优化”),但第二点是可靠的——编译器根本不允许这样做这种优化,永远。

标签: c# performance arcgis


【解决方案1】:

简单地说,编译器如何知道pcoll.PointCount 在调用之间是否会发生变化?它不能安全地假设该值将保持不变,因此它无法通过缓存对pcoll.PointCount 的第一次调用的值来优化此代码。

【讨论】:

  • 有时很简单,我通过实现自己的属性来检查这一点。很明显,调试器会在每次迭代中逐步执行,谢谢。
【解决方案2】:

在此期间它可能已经改变了。

确实,每次迭代都测试i &lt; pcoll.PointCount 而不仅仅是使用foreach(var point in pcoll) 的原因之一正是因为认为集合可能在此期间发生变化,而枚举器不保证应对他们列举的集合的变化。

这与例如通过局部变量访问的数组不同,因为通过局部变量访问的数组的Length 可以更改的唯一方法是在本地进行更改。

尽管如此,值得记住的是,编译器经常会跳过一些明显的优化,因为众所周知,抖动也会进行相同的优化。

【讨论】:

  • 其实不使用foreach的原因是ESRI提供的PointCollection类没有实现枚举器。 S这当然很烦人,但就是这样。
  • 真的吗? help.arcgis.com/en/webapi/silverlight/apiref/… 表示它是 ObservableCollection&lt;MapPoint&gt; 的后裔。 GetEnumerator() 会抛出异常吗?仍然这样做的原因之一是 for 是如果您想防止对集合进行类似更改。
  • 对不起,我提到了IPointCollection-interface(见这里:help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/…),我们甚至没有任何PointCollection-class,只有某种多部分几何(例如多点)。但我实际上是第一个
  • 嗯。这烦人。
  • 我不知道为什么来自 ESRI 的人决定根本不实现 IEnumerator(对于他们没有实现的其他类),也许可变性可能是一个原因
【解决方案3】:

字段的预期优化是正确的。但是property有setter/getter(访问property其实就是把它们当作方法调用),所以编译器会很难去优化它。

要修复,请将其设为字段或读取一次

var max = pcoll.PointCount;
for (int i = 0; i < max; i++) { /* ... */ }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-18
    • 1970-01-01
    • 2021-02-01
    • 2015-05-13
    • 2016-02-14
    • 2011-12-13
    • 1970-01-01
    相关资源
    最近更新 更多