我看到很多这样的代码由Java开发人员和Java教师编写:
for ( int x = 0 ; x < myArray.length ; x++ )
accum += (mean() - myArray[x]) * (mean() - myArray[x] );
我对此非常批评,因为对于数组中的每个元素,都会调用mean()两次,只需要调用一次:
double theMean = mean();
for ( int x = 0 ; x < myArray.length ; x++ )
accum += (theMean - myArray[x]) * (theMean - myArray[x]);
Java中的优化是否可以使第一个例子可以接受?我是否应该停止向开发人员介绍此事?
***更多信息。样本数组存储为实例变量。 mean()必须遍历数组并在每次调用时计算平均值。
答案 0 :(得分:1)
你是对的。你的方式(第二个代码示例)更有效。我不认为Java可以优化第一个代码示例只调用mean()
一次并重新使用它的返回值,因为mean()
可能有副作用,所以编译器不能这样做如果您的代码调用它两次,则决定调用它一次。
答案 1 :(得分:1)
让你的开发人员独自一人,没关系 - 它是可读的并且可以工作,而不会引入不必要的名称和变量。
优化只能在性能监控工具的指导下完成,该工具可以显示您实际上在哪里慢。并且,通常,通过考虑应用程序的大规模架构而不是逐行字节码优化来更有效地增强性能,这是昂贵且通常无益的。
答案 2 :(得分:1)
您的版本可能运行得更快,尽管优化编译器可能能够检测mean()
方法是否每次都返回相同的值(例如,如果值是硬编码的或存储在字段中)并消除方法调用。
如果出于效率原因建议进行此更改,则可能会因过早优化而受到影响。在适当的负载下,在适当的环境中度量之前,您还不知道系统中的瓶颈在哪里。即便如此,改进的硬件通常比开发人员的时间更具成本效益。
如果你推荐它,因为它会消除重复,那么我认为你可能会处于更强的地位。如果mean()
方法也接受了参数,那么将它从循环中拉出并且只调用一次方法是特别合理的。
答案 3 :(得分:0)
通常编译器不会优化方法调用,因为它无法知道返回值是否相同(当mean
处理数组时尤其如此,因为它无法检查结果是否可以缓存)。所以是mean()
方法将被调用两次。
在这种情况下,如果您确定数组保持不变,无论循环中x
和accum
的值如何(更一般地说,无论程序值是否有任何变化) ),然后第二个代码更优。
答案 4 :(得分:0)
是的,有些编译器会根据您的说法对其进行优化。
是的,你应该停止对开发人员这一点。
我认为您首选的方式更好,但主要不是因为优化。更清楚的是,如果它不涉及方法调用,则两个地方的值都相同,特别是在方法调用比此处的方法调用更复杂的情况下。
就此而言,我认为最好写
double theMean = mean();
for (int x=0; x < myArray.length; x++)
{ double curValue = myArray[x];
double toSquare = theMean - curValue;
accum += toSquare * toSquare;
}
因为这样可以更容易地确定您正在对正在积累的内容进行平方,以及正在进行平局的内容。