【问题标题】:Using same reference variable vs separate variables. Expense of reference variable in .Net使用相同的参考变量与单独的变量。 .Net 中参考变量的费用
【发布时间】:2011-12-01 09:14:28
【问题描述】:

我不确定这个问题是不是很傻,但我真的很想得到一些意见。我将直接提供一个我目前正在做的事情的例子。

我正在使用 HtmlAgilityPack 来解析一些 HTML 页面。

我的代码中有一个方法,它接收 HtmlDocument 并进行解析。目前,代码是这样的:

private void OperateOnDocument (HtmlDocument pageSource)
{
  HtmlNode node;
  node = pageSource.DocumentNode.SelectSingleNode (/*XPath to find a node */);
  // do some operation on the extracted HtmlNode.

  node = pageSource.DocumentNode.SelectSingleNode (/* XPath to find another node */);
  // do some operation on the newly acquired node.

  // Likewise, reuse the same reference variable "node" to extract all the nodes and operate on them.
}

优点:使用单个引用变量对所有节点进行操作。

缺点:您不知道单个解析提取的节点是什么,因为所有提取的节点都有不同的值和用途(一个节点可能包含费率,另一个可能包含城市名称。)

另一种方法是:

private void OperateOnDocument (HtmlDocument pageSource)
{      
  HtmlNode idNode = pageSource.DocumentNode.SelectSingleNode (/*XPath to find the node containing id*/);
  // parse the text and store it in string.

  HtmlNode rateNode = pageSource.DocumentNode.SelectSingleNode (/* XPath to find the node containing the rates */);
  // parse the text into decimal.

  // Likewise, use separte meaningful names of reference variables to extract all the nodes and operate on them.
}

优点:为每个正在操作的节点单独命名有意义的名称。

缺点:有时,操作数可能会增加到 10;因此,有 10 个不同的参考变量。

那么,我的问题是第二种方法是否真的值得做?或者由于参考变量太多,它可能会有点昂贵? .Net 中的这些变量有多昂贵?或任何其他一般的语言/框架?

【问题讨论】:

    标签: .net reference language-design


    【解决方案1】:

    如果您担心做某事的成本,那就衡量它。如果您无法衡量差异,那么差异就可能无关紧要(如果重要,您就可以衡量它)。

    要回答您更具体的问题,变量没有任何内在成本。在 CPU 上实际执行的代码中不存在变量。它们是源代码级别的构造,编译器没有义务在源代码变量与执行的push 指令或使用的寄存器或其他任何内容之间创建某种一对一的映射。代码中的单个变量可以对应于几个不同寄存器的使用(编译器可能会不时选择移动它),或者几个不同的变量可能最终都共享同一个寄存器,因为它们从未在同一时间。

    编译器所做的许多事情之一就是确定变量的生命周期。什么时候第一次使用,最后一次使用是什么时候?您何时声明它或它何时超出范围并不重要。

    编译器常用的将代码转换为更易于优化的形式的转换是将每个赋值转换为新的、唯一的变量,基本上就像在第二个示例中一样。这就是编译器更喜欢使用代码的方式,因为现在它可以清楚地看到依赖关系。在第一种情况下,看起来好像同一个变量必须存在于整个函数中,并且可以重复用于两个操作。在第二种情况下,我们可以很容易地看到它们是独立的、独立的变量,并且我们可以看到它们的生命周期没有重叠(idNoderateNode 的声明之后没有使用)。

    两个版本可能会生成完全相同的代码,但第二个版本更接近优化编译器在内部对代码所做的操作。

    【讨论】:

    • 感谢您的精彩回答,您给了我一些我不知道的信息。谢谢! :)
    【解决方案2】:

    我的理解是,这并不重要。编译器(在发布模式下!)对变量的使用有很好的了解。它应该能够检测到在您分配rateNode 时不再使用idNode,因此甚至可以重新使用该内存位置。

    另见this question

    【讨论】:

    • 我认为你是对的。我唯一的疑问是 GC 不会在不再使用后立即删除该节点......你怎么看?
    • 我同意@Marco。我也有同样的疑问。参考文献会不会越来越多?
    • 我看到您编辑了指向 Eric Lippert 的答案的答案:好吧,如果他这么说,我相信它!赞成;)
    • @Hans Kesting。我在编辑后看到了您的链接。好的。似乎可读性优于不必要的重用。
    • 假设编写编译器(或垃圾收集器)的人不是脑死亡的猴子通常会有所帮助。假设他们至少有平均水平的智力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    • 1970-01-01
    • 2015-02-17
    • 1970-01-01
    相关资源
    最近更新 更多