我正在扩展和改进 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/