包含许多输出为常量的“if”的临界循环:如何节省条件测试?对于Java;)



我刚刚读了这个线程,其中包含许多"if"输出是常量的:如何节省状态测试?

和这个常数嵌入循环条件优化在c++与gcc,这正是我想在Java中做的。

我有一些if条件被调用了很多次,这些条件由初始化时定义的属性组成,这些属性不会改变。

Javac是否会通过删除未使用的条件分支来优化字节码,从而避免花时间测试它们?我是否必须将属性定义为final或者它是无用的?

谢谢你的帮助,

Aurelien

Java编译时优化非常缺乏。如果您可以使用switch语句,它可能会进行一些微不足道的优化。如果属性的数量非常大,那么HashMap将是您最好的选择。

我最后要说的是,这种事情很少会成为瓶颈,试图过早地优化它会适得其反。如果您的代码实际上经常被调用,那么JIT优化器将尽最大努力使您的代码运行得更快。只要说出你想要发生的事情,只有当你发现真正值得花时间优化它时才担心"如何"。

在OO语言中,解决方案是使用委托或命令模式来代替if/else林。

所以你的属性需要实现一个像IAttribute这样的通用接口,它有一个方法run()(或使所有属性实现Runnable)。

现在你可以简单地调用这个方法,而不需要在循环中做任何决定:

for(....) {
    attr.run();
}

如果你不能给你的属性添加方法,那就有点复杂了。在这种情况下,我的解决方案是使用enum s和包含可运行程序的EnumMap。对EnumMap的访问几乎就像对数组的访问(即0(1))。

for(....) {
    map.get(attr).run();
}

我不知道关于这方面的Java细节,但是您可能想要研究一种称为Memoization的技术,它允许您在表中查找函数的结果,而不是调用函数。有效地,记忆使您的程序"记住"给定输入的函数的结果。

尝试用运行时多态性替换if。不,这并不像你想的那么奇怪。

例如:

for (int i=0; i < BIG_NUMBER; i++) {
  if (calculateSomeCondition()) {
    frobnicate(someValue);
  } else {
    defrobnicate(someValue);
  }
}

然后将其替换为以下内容(Function取自Guava,但可以替换为任何其他合适的接口):

Function<X> f;
if (calculateSomeCondition()) {
  f = new Frobnicator();
else {
  f = new Defrobnicator();
}
for int (i=0; i < BIG_NUMBER; i++) {
  f.apply(someValue);
}

方法调用在大多数现代jvm上都是非常高度优化的,即使(或特别是)只有几个可能的调用目标。

最新更新