Overriding与if语句的性能

H-M*_*an2 5 java oop performance if-statement

我正在扩展和改进Java应用程序,该应用程序也使用小型DSL进行长时间运行的搜索(详细地说,它用于模型查找,是的,它通常是NP-Complete).

在此搜索过程中,我想在控制台上显示一个小进度条.由于DSL的通用结构,我无法计算整体搜索空间大小.因此我只能输出第一个"回溯"语句的进度.

现在问题是:我可以为每个回溯语句使用一个标志来指示此语句应该报告进度.在评估语句时,我可以使用if语句检查标志:

public class EvalStatement {
  boolean reportProgress;

  public EvalStatement(boolean report) {
     reportProgress = report;
  }

  public void evaluate() {
    int progress = 0;

    while(someCondition) {
      // do something

      // maybe call other statement (tree structure)

      if (reportProgress) {
         // This is only executed by the root node, i. e.,
         // the condition is only true for about 30 times whereas
         // it is false millions or billions of times
         ++progress;
         reportProgress(progress);
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我也可以使用两个不同的类:

  • 一个什么都不做的课
  • 正在执行输出的子类

这看起来像这样:

public class EvalStatement {
  private ProgressWriter out;
  public EvalStatement(boolean report) {
      if (report)
        out = new ProgressWriterOut();
      else
        out = ProgressWriter.instance;     
  }
  public void evaluate() {
    while(someCondition) {
      // do something
      // maybe call other statement (tree structure)
      out.reportProgress(progress);
    }
  }
}

public class ProgressWriter {
  public static ProgressWriter instance = new ProgressWriter();
  public void reportProgress(int progress) {}
}

public class ProgressWriterOut extends ProgressWriter {
  int progress = 0;
  public void reportProgress(int progress) {
    // This is only executed by the root node, i. e.,
    // the condition is only true for about 30 times whereas
    // it is false millions or billions of times
    ++progress;
    // Put progress anywhere, e. g., 
    System.out.print('#');
  }
}
Run Code Online (Sandbox Code Playgroud)

现在真正的问题是:

  • 该方法的Java查找是否比if语句更快地调用?
  • 另外,接口和两个独立类会更快吗?

我知道Log4J建议在日志调用周围加一个if语句,但我认为主要原因是构造参数,特别是字符串.我只有原始类型.

编辑:我澄清了一点代码(经常被称为...单例的用法在这里无关紧要).

此外,我进行了两次长期的搜索运行,其中if-statement和操作调用分别在一台机器上执行了1.840.306.311次:

  • if版本耗时10h 6min 13sek(每秒50.343次点击)
  • or版本耗时10h 9min 15sek(每秒50.595次点击)

我想说,这并没有给出真正的答案,因为0.5%的差异在于测量公差.

我的结论是:他们的行为或多或少都是一样的,但是从凯恩的答案中猜测,最重要的方法可能在长期内更快.

chu*_*ubs 5

我认为这是过度优化的教科书定义.您甚至不确定自己是否存在性能问题.除非您在该部分进行了数百万次呼叫,否则如果您对其进行了分析,它甚至都不会显示在您的热点报告中.如果语句和方法调用大约需要纳秒才能执行.因此,为了使它们之间存在差异,您最多只能节省1-10ns.对于那甚至被人类认为是慢的,它需要在100毫秒的量级,并且如果他们的用户甚至像主动点击等那样关注,如果他们正在观看进度条他们不是甚至会注意到它.

假设我们想看看是否增加了1秒的额外时间,你发现其中一个可以节省10秒(这可能节省了1-4ns).这意味着你需要将该部分称为100,000,000次以节省1s.我可以保证,如果你有1亿个电话,你会发现10个其他区域比那里的if或polymorphism更昂贵.看起来有点愚蠢地辩论10ns的优点,你可能会节省1s不是吗?

我会更关心你使用单身而不是表现.


Kan*_*ane 1

真正回答这个问题的唯一方法是在正常情况下尝试两者并分析代码。有很多变数。

也就是说,如果我必须猜测的话,我会这么说:

一般来说,if 语句编译为比方法调用更少的字节码,但通过 JIT 编译器优化,您的方法调用可能会被内联,这不是字节码。此外,通过 if 语句的分支预测,成本是最小的。

同样,一般来说,如果您应该在每次运行循环时进行报告,那么使用接口会比测试更快。从长远来看,加载两个类、测试一次并实例化一个类的成本将低于运行特定测试十亿次。从长远来看。

同样,更好的方法是在现实世界的示例中以两种方式分析代码,甚至可能报告您的结果。但是,我很难看到这是您的应用程序的性能瓶颈...如果速度是一个问题,您的时间可能最好花在其他地方进行优化。