java - 重写与 if 语句的性能

标签 java performance oop if-statement

我正在扩展和改进 Java application它还使用小型 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);
      }
    }
  }
}

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

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

这看起来像这样:

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('#');
  }
}

现在真正的问题是:

  • 要调用的方法的 Java 查找是否比 if 语句更快?
  • 此外,一个接口(interface)和两个独立的类会不会更快?

我知道 Log4J 建议在日志调用周围放置一个 if 语句,但我认为主要原因是参数的构造,尤其是字符串。我只有原始类型。

编辑: 我稍微澄清了代码(所谓的经常调用...单例的用法在这里无关紧要)。

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

  • if 版本耗时 10 小时 6 分钟 13 秒(每秒 50.343 次“点击”)
  • 版本耗时 10 小时 9 分钟 15 秒(每秒 50.595 次“点击”)

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

我的结论:它们的行为或多或少是相同的,但从长远来看,最重要的方法可能会更快,正如凯恩在答案中所猜测的那样。

最佳答案

我认为这是过度优化的教科书定义。您甚至不确定自己是否存在性能问题。除非您在该部分进行了数百万次调用,否则如果您对它进行分析,它甚至不会显示在您的热点报告中。 If 语句和方法调用在纳秒级执行。因此,为了区分它们,您说的是最多节省 1-10ns。为了让人类认为它很慢,它需要在 100 毫秒的数量级,而且如果他们的用户甚至正在注意,比如主动点击等。如果他们正在看进度条,他们就不会甚至会注意到它。

假设我们想看看这是否增加了 1 秒的额外时间,您发现其中一个可以节省 10 纳秒(这可能相当于节省了 1-4 纳秒)。所以这意味着您需要将该部分调用 100,000,000 次才能节省 1 秒。我可以向您保证,如果您进行了 1 亿次调用,您会发现其他 10 个区域比那里的 if 或多态性选择更昂贵。就可能节省 1 秒的机会来争论 10 纳秒的优点似乎有点愚蠢,不是吗?

与性能相比,我更关心您对单例的使用。

关于java - 重写与 if 语句的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7958108/

相关文章:

ruby-on-rails - 是否有用于 Ruby on Rails 的分析 gem/插件?

android - 如何在 Nvidia Shield 上正确计时 Android RenderScript 代码

Java - 解析字符串 - String.split() 与 Pattern 和 Matcher

java - Spring AOP : Advice not called in abstract class

algorithm - 选择一对不重叠的回文子串的方法数

Java 访问实例化的对象

具有多个初始化方法的 Python 子类?

c++ - 在 C++ 中覆盖

java - 主题的不同布局目录

java - 核心 Java 和 JVM 安全性防止代码注入(inject)