java = 效率_Java循环效率

我已经运行了你提供的代码,也惊讶地发现这些性能差异.由好奇心引导我开始调查,发现确实尽管这些循环似乎在做同样的事情,但是它们之间有一些重要的区别.

第一次运行这些循环后的结果是:

for loop: 1.43100

do-while: 0.51300

while: 1.54500

但是,当我运行这三个循环至少10次时,这些循环的性能几乎相同.

for loop: 0.43200

do-while: 0.46100

while: 0.42900

JIT可以随时间优化这些循环,但是必须有一些不同之处,导致这些循环具有不同的初始性能.其实实际上有两个区别:

> do-while循环的执行次数比for循环和while循环更少

为简单起见,假设L = 1

long s1 = 0;

for (int i=0; i < L; i++) {

for (int j = 0; j < L; j++) {

s1 += 1;

外环:0 < 1

内循环:0 < 1

内环:1 < 1

外环:1 < 1 4次比较

int i = 0;

long s2 = 0;

do {

i++;

int j = 0;

do {

s2 += 1;

j++;

} while (j < L);

} while (i < L);

内环:1 < 1

外环:1 < 1 2次比较

>不同的生成字节码

为了进一步调查,我已经稍稍改变了你的班级,不会影响到班级的工作.

public class Loops {

final static int L = 100000; // number of iterations per loop

public static void main(String[] args) {

int round = 10;

while (round-- > 0) {

forLoop();

doWhileLoop();

whileLoop();

}

}

private static long whileLoop() {

int i = 0;

long s3 = 0;

while (i++ < L) {

int j = 0;

while (j++ < L) {

s3 += 1;

}

}

return s3;

}

private static long doWhileLoop() {

int i = 0;

long s2 = 0;

do {

int j = 0;

do {

s2 += 1;

} while (++j < L);

} while (++i < L);

return s2;

}

private static long forLoop() {

long s1 = 0;

for (int i = 0; i < L; i++) {

for (int j = 0; j < L; j++) {

s1 += 1;

}

}

return s1;

}

}

然后编译它并调用javap -c -s -private -l Loop来获取字节码.

首先是doWhileLoop的字节码.

0: iconst_0 // push the int value 0 onto the stack

1: istore_1 // store int value into variable 1 (i)

2: lconst_0 // push the long 0 onto the stack

3: lstore_2 // store a long value in a local variable 2 (s2)

4: iconst_0 // push the int value 0 onto the stack

5: istore 4 // store int value into variable 4 (j)

7: lload_2 // load a long value from a local variable 2 (i)

8: lconst_1 // push the long 1 onto the stack

9: ladd // add two longs

10: lstore_2 // store a long value in a local variable 2 (i)

11: iinc 4,1 // increment local variable 4 (j) by signed byte 1

14: iload 4 // load an int value from a local variable 4 (j)

16: iload_0 // load an int value from a local variable 0 (L)

17: if_icmplt 7 // if value1 is less than value2,branch to instruction at 7

20: iinc 1,1 // increment local variable 1 (i) by signed byte 1

23: iload_1 // load an int value from a local variable 1 (i)

24: iload_0 // load an int value from a local variable 0 (L)

25: if_icmplt 4 // if value1 is less than value2,branch to instruction at 4

28: lload_2 // load a long value from a local variable 2 (s2)

29: lreturn // return a long value

现在的whileLooP的字节码:

0: iconst_0 // push int value 0 onto the stack

1: istore_1 // store int value into variable 1 (i)

2: lconst_0 // push the long 0 onto the stack

3: lstore_2 // store a long value in a local variable 2 (s3)

4: goto 26

7: iconst_0 // push the int value 0 onto the stack

8: istore 4 // store int value into variable 4 (j)

10: goto 17

13: lload_2 // load a long value from a local variable 2 (s3)

14: lconst_1 // push the long 1 onto the stack

15: ladd // add two longs

16: lstore_2 // store a long value in a local variable 2 (s3)

17: iload 4 // load an int value from a local variable 4 (j)

19: iinc 4,1 // increment local variable 4 (j) by signed byte 1

22: iload_0 // load an int value from a local variable 0 (L)

23: if_icmplt 13 // if value1 is less than value2,branch to instruction at 13

26: iload_1 // load an int value from a local variable 1 (i)

27: iinc 1,1 // increment local variable 1 by signed byte 1

30: iload_0 // load an int value from a local variable 0 (L)

31: if_icmplt 7 // if value1 is less than value2,branch to instruction at 7

34: lload_2 // load a long value from a local variable 2 (s3)

35: lreturn // return a long value

如果仔细观察,您将看到这两个字节码之间存在重大差异.

while循环(对于for循环也是如此)在字节码末尾定义了if语句(if_icmplt指令).这意味着要检查第一个循环的退出条件,必须调用到第26行的转换,并且类似地,转到第二个循环的第17行.

上述字节码是在Mac OS X上使用javac 1.6.0_45生成的.

概要

我认为不同量的比较加上在while和for循环字节码中存在goto指令是这些循环之间的性能差异的原因.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值