【问题标题】:Comparing a boolean value before setting it在设置之前比较布尔值
【发布时间】:2011-05-04 10:45:25
【问题描述】:

在C#中,当布尔变量的值设置为false当它是true时,我应该在设置它之前检查它是否是true还是只是设置它?

假设变量是true 50% 的时间,检查它是有意义的,因为比较更快。如果变量大部分时间是true,我应该跳过比较吗?

哪种做法更好?

方法一,先检查:

if (bVariable)
    bVariable = false;

方法二,设置即可:

bVariable = false;

方法 2 在哪些条件下是首选(如果有)?

【问题讨论】:

  • 过早优化。 IMO 无用优化。
  • 你不知道。如果第一要务是可读性,那么在上下文中首先检查可能更容易理解。
  • 在这种情况下以及 99.9% 的其他人都喜欢它,更快是无关紧要的。只要您不需要执行任何其他条件逻辑,只需将其设置为 false。
  • 我猜答案取决于很多因素,包括处理器本身(流水线、错过分支预测的成本、缓存等)。您是否尝试对此进行基准测试?我还假设在您的情况下这将是过早的(并且不必要的)优化,但我确实认为从(纯)科学的角度来看这个问题很有趣。
  • 这是一个变量。所以我确实知道。如果它是一个可能有副作用的属性,那就另当别论了。

标签: c# comparison boolean


【解决方案1】:

是什么让您认为比较更快?如果您正在编写的代码是在 C 编译器中完成的,那么 IF 语句将被分成至少两条指令——一条比较/分支指令和一条针对单个字的单个位的“设置”指令。

“set”将编译为一条指令。您的“优化”可能会使您的程序运行速度变慢,并导致您的程序可读性降低。只需设置变量,不要想太多小事。

CPU 不像数据库。您不必为数据修改付出高昂的代价。 您为访问主存和分支(if 语句)付出高昂的代价。分支成本性能,因为pipelining CPU 实际上在分支指令做出决定之前分支之后开始执行指令! (我知道,这种说法有点令人兴奋)。但这意味着 CPU 必须花费资源“guessing”你的 IF 语句的结果将是什么。如果它猜错了,它必须“扔掉”它猜到的所有指令的结果,它会在分支之后执行并重试。这不好。这就是为什么分店很贵的原因。

这个故事的寓意不是你不应该优化,而是你不应该在不完全了解优化的含义的情况下进行优化。在这种情况下,如果您选择了选项 1,您最终可能会得到一个较慢的应用程序,该应用程序的启动可读性较差。

实际上,如果您真的对这类事情感兴趣,您应该绝对获取一份Code Complete 的副本。它充满了关于这类事情的讨论,并且写得非常出色。

【讨论】:

  • 我听说过关于 Code Complete 的好消息,一定会去看看。
【解决方案2】:

不要让生活复杂化。就设置好了。无论如何,首先检查实际上更昂贵,因为您现在必须在发回新值之前从 RAM(或缓存)中获取现有值。

(感谢 Colin Mackay...)首先测试还会因分支预测错误而导致管道停顿。

【讨论】:

  • FreshCode 最初评论的一个问题现已被删除。问题是为什么 if 语句更昂贵。我的回答:if 语句暗示处理器中的跳转操作。跳转操作意味着处理器必须清空其即将到来的指令流水线才能跳转到新的指令集。 (据我了解,我不是处理器专家)
  • 因为您可能不得不将旧值拖出 RAM,这会使 CPU 停顿数百个周期,而仅设置该值通常会以最小的延迟直接进入 L1 缓存。跨度>
  • 首先检查意味着值并不总是改变。变化的频率取决于变量的最可能值。假设在我的情况下bVariable 很少为真,那么设置该值似乎很浪费。我同意在 99% 的情况下,这将是过早的优化,但是如果必须对跨越多个页面的 巨大 数据集中的每条记录进行优化呢?
  • @Marcelo:我对 CPU 缓存不太了解,但为什么只设置值比检查它的开销少?如果不是更多的话,设置该值不会同样密集吗?
  • @FreshCode:它可能不需要 RAM 命中。写入可能会填满缓存并在完成之前强制刷新 RAM。正如@Colin 指出的那样,直觉在这方面是一个糟糕的指南。当我建议你证明每个人都错了时,我并不是在开玩笑。如果您对其进行编码,由于问题结构的某些特殊性,您实际上可能会让我们所有人感到惊讶。不过,我想说这种情况发生的可能性很小。
【解决方案3】:

应该首选方法 2,因为它更简单地表达了相同的结果,使其更易于阅读,正如其他人所说的那样 - 因为像这种易读性这样简单的东西远比微不足道的性能问题重要得多。

但是,bVariable 可能是一个属性,在这种情况下,设置它可能会带来其他副作用 - 可能在性能和结果方面。

【讨论】:

    【解决方案4】:

    在 C# 中,答案是:总是首选方法 2。由于这是一个非常简单的优化,如果方法 1 真的更快,编译器就会这样做。

    编辑:

    Donald Knuth 对您的方法 1 提出了一些建议,例如“过早的优化是万恶之源”和“代码应该首先由人类阅读,然后是机器阅读”。

    【讨论】:

      【解决方案5】:

      性能问题在这里无关紧要,因为像上面这样的简单 if 语句本质上接近于处理器的无操作。更重要的是,您的代码要清楚地向以后的读者传达其意图!

      托马斯

      【讨论】:

        【解决方案6】:

        我想说性能差异是如此微不足道,只需始终将其设置为 false。

        如果为假,将再次设置为假。 如果为真,则设置为假。

        不管怎样,在代码的最后,变量都会为假。

        通过始终将其设置为 false,无论如何您都可以使意图更加清晰。任何其他阅读代码的人都会立即看到,在该部分代码结束时,该值在所有情况下都是错误的。而如果你有一个 if 语句,他们将不得不更加努力地考虑它。

        仅出于维护目的,我主张将值设置为 false 而不管其原始值如何,因为它最终始终为 false。

        【讨论】:

          【解决方案7】:

          过早的优化是万恶之源。您无法说服我,这种“优化”会给您带来任何性能提升

          【讨论】:

            【解决方案8】:

            这似乎是一个太多的微优化,我真的认为编译器无论如何都会为你优化这一点。

            但是,如果您无论如何都希望最终值为false,我想简单地将其分配给false 更有意义。我的意思是为什么要检查你是否真的不需要关心价值。

            【讨论】:

              【解决方案9】:

              进行比较的唯一原因是当值更改时您需要执行额外的逻辑。

              如果你只是要分配它,如果你做额外的检查,它很可能会损害性能。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2017-10-10
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-05-05
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多