假设如下:您有两个函数,两个函数基本上都是相同的,这就是比较两个随机布尔函数和AND和OR操作符。但是,一个函数是用普通的条件运算符&和\来完成这个任务的,另一个函数使用的是位操作符&和\。
我认为这两个函数当然需要相同的时间来完成,,但--它们不需要。与“正常”条件运算符相比,按位进行比较所需的时间多出五分之一。
我很困惑,做了一些研究,并在Oracle的Java文档中找到了以下条件运算符的定义:
The && and || operators perform Conditional-AND and Conditional-OR operations on two boolean expressions. These operators exhibit "short-circuiting" behavior, which means that the second operand is evaluated only if needed.
&& Conditional-AND
|| Conditional-OR对于按位运算符:
The Java programming language also provides operators that perform bitwise and bit shift operations on integral types.
The bitwise & operator performs a bitwise AND operation.
The bitwise | operator performs a bitwise inclusive OR operation.嗯,这些定义并没有让我感到满意,我的问题仍然没有得到回答。因此,我做了更多的研究,并在这里发现了一个关于堆栈溢出的问题,关于位运算符对booleans的影响(Java中位运算符对布尔值的影响),但这也没有真正回答我的问题。
下面是我测试过的代码,它使用一个随机数生成器来获取随机的布尔值,以便相互比较,并在这段时间内循环。
import java.util.Random;
public class Main {
private static final long LOOPS = 100000000L;
private static Random rng = new Random();
public static final void main(String[] args)
{
System.out.println("Bitwise operator: "+loopWithBitwiseOperator(LOOPS));
System.out.println("Normal operator: "+loopWithNormalOperator(LOOPS));
}
public static long loopWithNormalOperator(long loops)
{
long startTime = System.currentTimeMillis();
for (long i = 0L; i < loops; i++)
{
if (rng.nextBoolean() || rng.nextBoolean())
{
i++;
}
if (rng.nextBoolean() && rng.nextBoolean())
{
i++;
}
}
return System.currentTimeMillis()-startTime;
}
public static long loopWithBitwiseOperator(long loops)
{
long startTime = System.currentTimeMillis();
for (long i = 0L; i < loops; i++)
{
if (rng.nextBoolean() | rng.nextBoolean())
{
i++;
}
if (rng.nextBoolean() & rng.nextBoolean())
{
i++;
}
}
return System.currentTimeMillis()-startTime;
}
}我收到了以下输出:
Bitwise operator: 2502
Normal operator: 1806因此,位运算符实际上比“正常”运算符慢。我的第一个想法是,也许随机数生成器生成的布尔值在运行时被处理得不一样,与另一个布尔值相比,它实际上比需要的要多,因为它是如何实际保存的。但后来我想,这可能是因为条件运算符的“短路”机制,它可能不适用于位运算符,它可能实际上需要两个值来进行比较。
我的假设正确吗?这一切为什么要发生?另一个例子--不代表Java逻辑运算符实际行为的特定行为?
一如既往,感谢您的帮助和澄清。
编辑:
按照评论中的要求,我尝试切换调用,并包含某种热身阶段,但仍然没有什么变化:
Normal operator: 1801
Bitwise operator: 2433发布于 2014-06-15 00:01:07
路易斯·沃瑟曼的评论是正确的诊断。对随机数发生器的调用次数对性能影响很大,因此短路是很重要的.我使用以下几种方法对程序进行了修改,以计算调用数:
private static boolean normalCountedRandom() {
normalCount++;
return rng.nextBoolean();
}我还在每次运行中做了多次测量,以消除任何启动效果问题。一个典型的产出是:
Bitwise operator: 1985
Normal operator: 1560
Bitwise operator: 1967
Normal operator: 1547
Bitwise operator: 2046
Normal operator: 1557
Bitwise operator: 2009
Normal operator: 1553
Bitwise Random calls: 800006428
Normal Random calls: 6000309314:3的比例与预期相符。每个if执行一个强制呼叫。如果使用短路运营商,其中只有一半会导致第二次呼叫,预期每if有1.5个呼叫,而没有短路的情况下,每if有2个呼叫。这个比率类似于性能比率,假设调用占了大部分时间,但不是所有时间。
短路行为记录在JLS中.从技术上讲,当应用于布尔操作数时,&和|是布尔逻辑运算符。“正常”运算符是有条件-和和有条件-或运算符。
通常情况下,最好避免迭代次数依赖于Random结果,尽管在这种情况下,迭代足够多,运行之间的差异很小。
https://stackoverflow.com/questions/24224687
复制相似问题