本地成员更快或实例成员

时间:2013-06-18 07:10:49

标签: java

以下代码证明method1比method2更快。任何人都可以评论这种行为的原因是什么。

class Trial {
        String _member;
        void method1() {
            for(int i=0;i<30480;i++) {
                _member += "test";
            }
        }
        void method2() {
            String temp="";
            for(int i=0;i<30480;i++) {
                temp += "test";
            }
            _member = temp;
        }

        public static void main(String args[]) {
            Trial t = new Trial();
            long startTime1 = System.currentTimeMillis();
            t.method1();
            long endTime1 = System.currentTimeMillis();
            long startTime2 = System.currentTimeMillis();
            t.method2();
            long endTime2 = System.currentTimeMillis();
            System.out.println(endTime1 - startTime1);
            System.out.println(endTime2 - startTime2);
        }
    }

3 个答案:

答案 0 :(得分:12)

  

以下代码证明method1比method2

更快

没有。它没有证明它。

这取决于很多因素。当我运行此代码时,我得到了

1403
1248

因此,在我的环境中,您的代码“证明”method1比method2 更慢

在进行基准测试时,您需要注意缓存和JVM预热等效果。

另见

了解更多信息。


我稍微重构了main方法:

...

static void doBenchmark() {
   Trial t = new Trial();

   long startTime1 = System.currentTimeMillis();
   t.method1();
   long endTime1 = System.currentTimeMillis();

   long startTime2 = System.currentTimeMillis();
   t.method2();
   long endTime2 = System.currentTimeMillis();

   System.out.println(endTime1 - startTime1);
   System.out.println(endTime2 - startTime2);
}

public static void main(String args[]) {

   for (int i = 0;  i < 20;  i++) {
      doBenchmark();
      System.out.println("----");
   }
}

这导致for - 循环的第一次迭代的值相似,但随后结果收敛并且不再显着不同:

1396
1133
----
1052
1070
----
688
711
----
728
726
----
715
709
----
...

即使有时method1似乎更快,有时method2 - 这很可能是由于测量不准确造成的。

答案 1 :(得分:0)

将jvm加热一段时间后,您会看到,方法2比方法1 更快。

这是我重新考虑的代码:

class Trial {
String _member;

  void method1() {
    for (int i = 0; i < 30480; i++) {
        _member += "test";
    }
  }

  void method2() {
    String temp = "";
    for (int i = 0; i < 30480; i++) {
        temp += "test";
    }
    _member = temp;
  }

  public static void main(String args[]) {
    Trial t = new Trial();

    for (int i = 0; i < 10; i++) { //warm up jvm
        t.method1();
        t.method2();
    }

    t = new Trial();

    long startTime1 = System.currentTimeMillis();
    t.method1();
    long endTime1 = System.currentTimeMillis();
    long startTime2 = System.currentTimeMillis();
    t.method2();
    long endTime2 = System.currentTimeMillis();
    System.out.println(endTime1 - startTime1);
    System.out.println(endTime2 - startTime2);
  }
}

结果如下:

----
2910
2894
----

但是对于实际的基准测试,你应该多次运行它并观察统计行为,然后才能得出任何结论!

答案 2 :(得分:0)

我已经修改了测试次数,但没有修改方法,这里使用 StringBuilder 2500在3000 时更快!

class Trial {
    StringBuilder _member = new StringBuilder(243840);
    void method1() {
        for (int i = 0; i < 30480; i++) {
            _member.append("test");
        }
    }

    void method2() {
        final StringBuilder temp = new StringBuilder(243840);
        for (int i = 0; i < 30480; i++) {
            temp.append("test");
        }
        _member = temp;
    }
    public static void main(final String args[]) {
        long startTime1 = System.nanoTime();
        new Trial().method1();
        long endTime1 = System.nanoTime();
        long startTime2 = System.nanoTime();
        new Trial().method2();
        long endTime2 = System.nanoTime();
        System.out.println(endTime1 - startTime1);
        System.out.println(endTime2 - startTime2);
        System.out.println("------------------");
        startTime1 = System.nanoTime();
        new Trial().method1();
        endTime1 = System.nanoTime();
        startTime2 = System.nanoTime();
        new Trial().method2();
        endTime2 = System.nanoTime();
        System.out.println(endTime1 - startTime1);
        System.out.println(endTime2 - startTime2);
    }
}

输出:

method1 then method2 with += in MILLIisecond
5563
5844
............................................
5437
6344

method2 then method1 with += in MILLIisecond
4625
5969
------------------
6531
4891

=====================================================

method1 then method2 with StringBuilder in NANOsecond
3530337
2074286
------------------
2058641
1983493
.....................................................

method2 then method1 with StringBuilder in NANOsecond
3430883
1698819
------------------
2065626
2144406

所以正如@Andreas所说,这不是测试表演的好方法。

要指出:使用声明大小的 StringBuilder (在Joshua Bloch的书中有效Java 项目51:注意字符串连接的性能
- < em>在可能的情况下更喜欢method2():String [Builder]在其中被声明,而不是在外面使用