【问题标题】:Is the C# or JIT compiler smart enough to handle this?C# 或 JIT 编译器是否足够聪明来处理这个问题?
【发布时间】:2013-12-13 21:06:05
【问题描述】:

假设我们有以下模型:

public class Father
{
    public Child Child { get; set; }
    public string Name { get; set; }

    public Father() { }
}

public class Child
{
    public Father Father;
    public string Name { get; set; }
}

以及以下实现:

var father = new Father();
father.Name = "Brad";
var child = new Child();
child.Father = father;
child.Name = "Brian";
father.Child = child;

现在我的问题是: coden-p #1 是否等同于coden-p #2?

或者运行coden-p #1是否需要更长的时间?

代码片段#1:

var fatherName = father.Child.Father.Child.Father.Child.Name;

代码片段 #2:

var fatherName = father.Name;

【问题讨论】:

  • 我的投票是YES
  • 是的,编译器不会优化它。
  • 值得注意的是,即使编译器没有优化第二个到第一个,代码sn-p的所有相关内存位置都将清楚地放入缓存中,因此实际上解决了再次在父子之间进行引用,并且增益将超级快,因为所有内容都已经在缓存中。
  • 抖动只是为了优化健全的代码而编写的,它不会消耗宝贵的 CPU 周期来寻找愚蠢的腻子。
  • @HansPassant 是的。虽然要确定什么是“理智的”并不总是那么容易。

标签: c# optimization compiler-construction


【解决方案1】:

C# 编译器不会对此进行优化,只会发出调用属性 getter 的所有操作。

另一方面,JIT 编译器可能会通过内联这些方法调用做得更好,但无法进一步优化,因为它不了解您的领域。优化这在理论上可能会导致错误的结果,因为您的对象图可以按如下方式构造:

var father = new Father
{
    Child = new Child
    {
        Father = new Father
        {
            Child = new Child
            {
                Father = new Father { ... }
            }
        }
    };

或者运行coden-p #1是否需要更长的时间?

答案是“是”,运行第一个代码 sn-p 需要更长的时间,因为 C# 和 JIT 都无法优化这个。

【讨论】:

  • 任何优化都可能导致错误的结果。这就是编译器在执行分析之前执行分析以证明其安全性的原因。
【解决方案2】:

不,代码 sn-ps 不等价。

第一个代码 sn-p 会给你一个NullReferenceException,正如预期的那样,因为你没有为father.Child分配任何东西。

即使您确实将子项分配给 father.Child 属性,编译器也不能假定这些值将始终保持这种状态,因此它无法从第一个 sn-p 中优化掉任何内容。

【讨论】:

  • 在我看来,简单的内联和分析可以确定在评估 (\.Father|\.Child)* 时值将保持不变。您能否详细说明为什么您认为编译器(csc.exe 和 JIT 编译器)不能这样假设?
  • @delnan:执行 sn-p 时值将保持不变,但编译器不能假定它们总是包含与第一次分配的值相同的值。
  • 好的,我假设初始化和属性访问在同一个方法中。从技术上讲,编译器仍然可以生成识别循环引用并为其提供快速路径的代码,但这纯粹是假设,我怀疑任何编译器都不会专门针对这种情况进行优化。
  • @Guffa:感谢关于father.Child 属性的提示。我相应地更改了我的代码。
  • JIT 无法知道引用的对象不会改变,首先是因为它会进行点优化,而不是完整的程序评估。其次是因为多线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-02
  • 1970-01-01
  • 2015-05-21
  • 2023-02-09
  • 2011-02-11
  • 1970-01-01
相关资源
最近更新 更多