就我而言,我使用的是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);
显然,第一个&#39;的执行时间。代码较少,因为它执行条件&#39; string.IsNullOrWhiteSpace(name)&#39;每个循环只有一次。而第二个&#39;代码(更好)在每次迭代时执行条件。
请考虑长循环执行时间而不是短循环,因为我知道当它很短时,性能不会有所不同。
答案 0 :(得分: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);
}
答案 1 :(得分:1)
您应该始终采用更容易理解和维护的方式。这意味着将重复代码减少到绝对最小值(DRY)。此外,这种微优化对许多系统来说并不重要。另请注意,较短的代码并不总是更好。
我想我会选择这样的话:
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()
方法太慢了,其他代码的性能完全无关紧要。如果你测量那么重复循环可以提高性能,你可以考虑改变它。