我最近使用JVisualVM分析了一些代码,发现有一个特定的方法占用了大量的执行时间,这是因为它经常被调用,而且执行速度很慢。该方法由一大块if语句组成,如下所示:(实际方法中大约有30个)
EcState c = candidate;
if (waypoints.size() > 0)
{
EcState state = defaultDestination();
for (EcState s : waypoints)
{
state.union(s);
}
state.union(this);
return state.isSatisfied(candidate);
}
if (c.var1 < var1)
return false;
if (c.var2 < var2)
return false;
if (c.var3 < var3)
return false;
if (c.var4 < var4)
return false;
if ((!c.var5) & var5)
return false;
if ((!c.var6) & var6)
return false;
if ((!c.var7) & var7)
return false;
if ((!c.var8) & var8)
return false;
if ((!c.var9) & var9)
return false;
return true;
有没有更好的方法来编写这些if语句,或者我应该从其他地方寻找提高效率的方法?
编辑:该程序使用进化科学来开发达到给定结果的路径。具体来说,为星际争霸2构建订单。这种方法检查特定的进化是否满足给定结果的条件。
4条答案
按热度按时间4bbkushb1#
首先,你使用的是
&
而不是&&
,所以你没有利用short circuit evaluation。也就是说,&
运算符要求&两边的条件都被求值。如果你真的在做一个按位AND
运算,那么这就不适用了,如果不是,请看下面。假设在不满足条件时返回true,则可以如下重写(我将
&
更改为&&
)。第二,你想把最有可能为真的条件移到表达式链的顶端,这样可以节省对剩余表达式的求值,例如
if (c1.var4 < var4)
有99%的可能性为真,你可以把它移到顶端。除此之外,除非这些条件遇到数据库或类似的情况,否则您会在此方法中花费大量的时间,这似乎有点奇怪。
6ljaweal2#
首先,尝试将
if
语句序列重写为一个语句(根据@dcp的答案)。如果这没有太大区别,那么瓶颈可能是
waypoints
代码。waypoints.size()
开销较大的某个集合类型。waypoints.size()
是一个很大的数defaultDestination()
价格昂贵state.union(...)
价格昂贵state.isSatisfied(...)
价格昂贵一种快速而简便的调查方法是将所有代码移到一个单独的方法中,然后查看分析器是否告诉您这是一个瓶颈。
如果这不是问题所在,那么您的问题就是难以解决的,唯一的解决方法就是找到一些聪明的方法来避免进行如此多的测试。
false
的顺序,则重新排列测试顺序可能会有所帮助。this
和c
很可能是同一个对象,那么对this == c
进行初始测试可能会有所帮助。hashCode
来缓存其返回值,并使用hashCode
来加快相等性测试(这是一个很长的机会......很多事情必须是“正确的”才能有所帮助)。hashCode
equality作为equality的代理...dbf7pr2w3#
和往常一样,最好的方法是自己测量。您可以通过调用
System.nanotime()
来检测此代码,以获得非常细粒度的持续时间。获得开始时间,然后计算方法的各个大块实际花费的时间。选择最慢的块,然后在其中放入更多的nanotime(
)调用。让我们知道您的发现。这对阅读你的问题的其他人会有帮助。所以这是我的底限猜猜...
优化if语句几乎没有什么可衡量的效果:这些比较都相当快。
我们假设问题在这里:
我猜waypoints是一个List,并且你没有覆盖size()方法,在这个例子中,List.size()只是访问一个示例变量,所以不要担心if语句。
for语句迭代List元素的速度非常快,所以for语句本身并不是它,尽管问题很可能出在它执行的代码上,赋值和返回不花时间。
这留下了以下潜在热点:
defaultDestination()
的一次调用。EcState.union()
的电话。EcState.isSatisfied()
的一次调用。我敢打赌,您的热点位于union()中,特别是因为它正在构建某种越来越大的航点集合。
首先使用nanetime()进行测量。
xn1cxnb44#
你不会找到太多的方法来真正加快速度,两个主要的方法是利用短路求值,如前所述,通过将
&
切换到&&
,并确保条件的顺序是有效的,例如,如果有一个条件丢弃了90%的可能性,则将该条件放在方法的第一位。