冗余/性能更好的代码 VS 优化/性能较差的代码

问题描述 投票:0回答:2

就我而言,我使用的是 C#,但问题的概念也适用于 Java。希望答案足够通用以涵盖两种语言。否则最好把问题分成两部分。

我一直在想哪一个是更好的做法。

编译器是否负责增强“第二个”代码,使其性能与“第一个”代码一样好?

是否可以同时获得“更好的性能”和“优化”代码?

冗余/更好的性能代码:

string name = GetName(); // returned string could be empty List<string> myListOfStrings = GetListOfStrings(); if(string.IsNullOrWhiteSpace(name) { foreach(string s in myListOfStrings) Console.WriteLine(s); } else { foreach(string s in myListOfStrings) Console.WriteLine(s + " (Name is: " + name); }

优化/性能较低的代码:

string name = GetName(); // returned string could be empty List<string> myListOfStrings = GetListOfStrings(); foreach(string s in myListOfStrings) Console.WriteLine(string.IsNullOrWhiteSpace(name) ? s : s + " (Name is: " + name);

显然“第一个”代码的执行时间较短,因为它每个循环仅执行一次条件“string.IsNullOrWhiteSpace(name)”。而“第二个”代码(更好)在每次迭代时执行条件。

请考虑较长的循环执行时间而不是较短的循环执行时间,因为我知道当循环执行时间较短时,性能不会有差异。

java c# performance
2个回答
3
投票
编译器是否负责增强“第二个”代码,使其性能与“第一个”代码一样好?

不,不能。

    它不知道布尔表达式在循环迭代之间不会改变。 代码有可能不每次都返回相同的值,因此被迫在每次迭代中执行检查。
  1. 布尔表达式也可能有副作用。 在这种情况下,它不会,但编译器无法知道这一点。 为了满足规范,执行此类副作用很重要,因此需要在每次迭代中执行检查。

  2. 因此,您需要问的下一个问题是,在这种情况下,执行您提到的优化是否“重要”? 在任何情况下,我都可以想象您所展示的确切代码,但可能不会。 检查速度非常快,几乎肯定不会成为瓶颈。 如果存在性能问题,几乎肯定会有更大的鱼。

  3. 也就是说,只需对示例进行一些更改即可使其变得重要。 如果布尔表达式本身的计算成本很高(即,它是数据库调用、Web 服务调用、某些昂贵的 CPU 计算等的结果),那么它可能是重要的性能优化。 另一种需要考虑的情况是如果布尔表达式有副作用会发生什么。 如果这是对
MoveNext

IEnumerator 调用怎么办? 如果只执行一次很重要,因为您不希望副作用发生 N 次,那么这就是一个

非常

重要的问题。


在这种情况下有几种可能的解决方案。

最简单的方法很可能只计算布尔表达式一次,然后将其存储在变量中: bool someValue = ComputeComplexBooleanValue(); foreach(var item in collection) { if(someValue) doStuff(item); else doOtherStuff(item); }

如果你想执行布尔值0-1次(即,在集合为空的情况下避免调用它一次),那么我们可以使用

Lazy

来延迟计算该值,但确保它最多仍然只被计算一次:

var someValue = new Lazy<bool>(() => ComputeComplexBooleanValue());
foreach (var item in collection)
{
    if (someValue.Value)
        doStuff(item);
    else
        doOtherStuff(item);
}

您应该始终首先选择更容易理解和维护的方式。这意味着将重复代码减少到绝对最小值(

DRY
)。此外,这种微观优化对于许多系统来说并不那么重要。另请注意,代码越短并不总是越好。

1
投票

string name = GetName(); // returned string could be empty bool nameIsEmpty = string.IsNullOrWhiteSpace(name); foreach (string s in GetListOfStrings()) { string messageAddition = ""; if (!nameIsEmpty) { messageAddition = " (Name is: " + name + ")"; } Console.WriteLine(s + messageAddition); // more code which uses the computed value.. // otherwise the condition can be moved out the loop } 我发现在方法调用中额外的

if

语句比

?:
 运算符更容易阅读,但这可能是个人喜好。

如果您想稍后提高性能,您应该分析您的应用程序并首先开始优化最慢的代码部分。也许你的

GetListOfStrings()
方法太慢了,以至于其他代码的性能完全无关。如果您
测量到
重复循环可以显着提高性能,您可以考虑更改它。


© www.soinside.com 2019 - 2024. All rights reserved.