在我们编程的过程中经常会遇到这样的问题。
for
(
int
i
=
0
;i
<
n;i
++
)
{
String str = //
}
String str = null ;
for ( int i = 0 ;i < n;i ++ ) {
str = //
}
在印象中一直认为方法二的性能好于方法一,但是差距应该很小。但因为一位别人的回文说方法一极大的影响了性能,所以想写个例子证明一下相差很小。例子如下:
方法一:3300毫秒左右
方法二:4300毫秒左右
结果刚好相反,于是更改方法
public class TestOt {
public static void main(String[] args) {
long n=1000000000;
long start = System.currentTimeMillis();
test1(n);
long end = System.currentTimeMillis();
System.out.println(end-start);
}
public static void test1(long n){
for (int i=0;i<n;i++){
String str = null;
}
}
public static void test2(long n){
String str = null;
for (int i=0;i<n;i++){
}
}
}
结果依旧。
没办法,取得字节码,对比
结果是感觉还是应该是方法二快,那为什么反而方法一快了1秒左右呢?
不得而知,现在我个人猜测的想法是可能有两种情况:
1,JLS的底层定义决定的,有什么特殊的优化?
2,因为方法二比方法一虽然少了在循环中的部分,但是引用的声明周期反而是更长了,是否因为引用存在造成了方法二的栈操作消耗了大部分时间?
猜想一有待于JLS文档的查阅,我会在有空的时候查询,猜想二正在想办法证明。
看文章的朋友,如果谁了解麻烦指点一下,是我的测试方法写的有问题,还是别的原因,谢谢。
最后:问题已经基本了解了原因,见回复中的讨论,谢谢--daydream 的帮忙。
String str = //
}
String str = null ;
for ( int i = 0 ;i < n;i ++ ) {
str = //
}
在印象中一直认为方法二的性能好于方法一,但是差距应该很小。但因为一位别人的回文说方法一极大的影响了性能,所以想写个例子证明一下相差很小。例子如下:
public
class
TestOt
{
public static void main(String[] args) {
long n=1000000000;
long start = System.currentTimeMillis();
test2(n);
long end = System.currentTimeMillis();
System.out.println(end-start);
}
public static void test1(long n){
for (int i=0;i<n;i++){
String str = "";
}
}
public static void test2(long n){
String str = null;
for (int i=0;i<n;i++){
str = "";
}
}
}
测试的结果是当n=10亿次的时候差距是1秒,所以说差距应该是很小的,符合我原始的记忆,但是另一个问题来了,测试的结果是
public static void main(String[] args) {
long n=1000000000;
long start = System.currentTimeMillis();
test2(n);
long end = System.currentTimeMillis();
System.out.println(end-start);
}
public static void test1(long n){
for (int i=0;i<n;i++){
String str = "";
}
}
public static void test2(long n){
String str = null;
for (int i=0;i<n;i++){
str = "";
}
}
}
方法一:3300毫秒左右
方法二:4300毫秒左右
结果刚好相反,于是更改方法
public class TestOt {
public static void main(String[] args) {
long n=1000000000;
long start = System.currentTimeMillis();
test1(n);
long end = System.currentTimeMillis();
System.out.println(end-start);
}
public static void test1(long n){
for (int i=0;i<n;i++){
String str = null;
}
}
public static void test2(long n){
String str = null;
for (int i=0;i<n;i++){
}
}
}
没办法,取得字节码,对比
public
class
TestOt
extends
java.lang.Object
{
public TestOt();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void test1(int);
Code:
0: iconst_0
1: istore_1
2: goto 10
5: aconst_null
6: astore_2
7: iinc 1, 1
10: iload_1
11: iload_0
12: if_icmplt 5
15: return
public static void test2(int);
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: goto 10
7: iinc 2, 1
10: iload_2
11: iload_0
12: if_icmplt 7
15: return
}
public TestOt();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void test1(int);
Code:
0: iconst_0
1: istore_1
2: goto 10
5: aconst_null
6: astore_2
7: iinc 1, 1
10: iload_1
11: iload_0
12: if_icmplt 5
15: return
public static void test2(int);
Code:
0: aconst_null
1: astore_1
2: iconst_0
3: istore_2
4: goto 10
7: iinc 2, 1
10: iload_2
11: iload_0
12: if_icmplt 7
15: return
}
结果是感觉还是应该是方法二快,那为什么反而方法一快了1秒左右呢?
不得而知,现在我个人猜测的想法是可能有两种情况:
1,JLS的底层定义决定的,有什么特殊的优化?
2,因为方法二比方法一虽然少了在循环中的部分,但是引用的声明周期反而是更长了,是否因为引用存在造成了方法二的栈操作消耗了大部分时间?
猜想一有待于JLS文档的查阅,我会在有空的时候查询,猜想二正在想办法证明。
看文章的朋友,如果谁了解麻烦指点一下,是我的测试方法写的有问题,还是别的原因,谢谢。
最后:问题已经基本了解了原因,见回复中的讨论,谢谢--daydream 的帮忙。