在java中将逻辑拆分为多个方法会降低执行速度吗?如果是,那么我们应该避免重新分解代码

时间:2013-06-23 08:36:22

标签: java performance refactoring

http://s24.postimg.org/9y073weid/refactor_vs_non_refactor.png enter image description here 这里是针对简单加法操作的重新分解和非重新分解代码的执行时间(以纳秒为单位)的结果。 1到5是代码的连续运行。 我的目的只是为了找出将逻辑分解为多个方法是否会导致执行变慢,这里的结果表明,只需将相当多的时间放在堆栈上即可。

我邀请那些已经对此进行过一些研究的人或者想要调查这个领域来纠正我,如果我做错了什么并从中得出一些结论性结果。 在我看来,是的代码重新分解确实有助于使代码更加结构化和可理解,但在时间关键系统,如实时游戏引擎,我宁愿不重新考虑。

以下是我使用的简单代码:

    package com.sim;

public class NonThreadedMethodCallBenchMark {

public static void main(String args[]){
    NonThreadedMethodCallBenchMark testObject = new NonThreadedMethodCallBenchMark();
    System.out.println("************Starting***************");
    long startTime =System.nanoTime();

    for(int i=0;i<900000;i++){
        //testObject.method(1, 2); // Uncomment this line  and comment the line below to test refactor time
        //testObject.method5(1,2); // uncomment this line and comment the above line to test non refactor time
    }
    long endTime =System.nanoTime();
    System.out.println("Total :" +(endTime-startTime)+" nanoseconds");
}

public int method(int a , int b){
    return method1(a,b);
}
public int method1(int a, int b){
    return method2(a,b);
}
public int method2(int a, int b){
    return method3(a,b);
}
public int method3(int a, int b){
    return method4(a,b);
}
public int method4(int a, int b){
    return method5(a,b);
}
public int method5(int a, int b){
    return a+b;
}
public void run() {
    int x=method(1,2);
}

}

2 个答案:

答案 0 :(得分:2)

是的,额外的方法调用需要花费额外的时间(除了在编译器/抖动实际进行内联的情况下,我认为其中有些会有时会这样做,但在你会发现很难控制的情况下)。

除了代码中最昂贵的部分之外,您不应该担心这一点,因为在大多数情况下您将无法看到差异。在性能无关紧要的情况下,您应该重构以最大限度地提高代码清晰度。

我建议您随意重构,偶尔使用分析器测量性能以找到昂贵的部件。只有当分析器显示某些特定代码在很长一段时间内使用时,您是否应该担心该特定代码中的函数调用(或其他速度与清晰度权衡)。您会发现性能瓶颈通常出现在您不会猜到的地方。

答案 1 :(得分:2)

你应该考虑不做任何有用的代码可以被优化掉。如果您不小心,您可以计算检测代码所需的时间,而不是运行代码。如果使用多种方法,则检测无用代码可能需要更长时间,因此会产生不同的结果。在代码预热后,我会一直关注稳态性能。

对于代码中最昂贵的部分,将会内联小方法,因此它们不会对性能成本产生任何影响。可能发生的是

  • 较小的方法可以更好地优化,因为复杂的方法可以打败优化技巧。
  • 可以消除较小的方法,因为它们是内联的。

如果你没有预热代码,它可能会变慢。但是,如果很少调用代码,则不太可能重要(低延迟系统除外,在这种情况下,我建议您在启动时预热代码)

如果你跑

System.out.println("************Starting***************");

for (int j = 0; j < 10; j++) {
    long startTime = System.nanoTime();
    for (int i = 0; i < 1000000; i++) {
        testObject.method(1, 2);
        //testObject.method5(1,2); // uncomment this line and comment the above line to test non refactor time
    }
    long endTime = System.nanoTime();
    System.out.println("Total :" + (endTime - startTime) + " nanoseconds");
}

打印

************Starting***************
Total :8644835 nanoseconds
Total :3363047 nanoseconds
Total :52 nanoseconds
Total :30 nanoseconds
Total :30 nanoseconds

注意:30纳秒是执行System.nanoTime()调用所需的时间。内部循环和方法调用已被消除。