jvm 本地成员或示例成员速度更快

n3ipq98p  于 2022-11-07  发布在  其他
关注(0)|答案(3)|浏览(147)

下面的代码证明了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);
        }
    }
2ic8powd

2ic8powd1#

将JVM预热一段时间后,您将看到,method 2比method 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
----

但是对于实际的基准测试,你应该运行它几次,观察统计行为,只有这样你才能得出任何结论!

wj8zmpe1

wj8zmpe12#

我已经修改了测试的次数,但是没有修改方法,这里用StringBuilder2500 * 达到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(在约书亚Bloch的书Effective Java * 第51项中:请注意字符串连接的性能 *)

    • 首选方法2()* 如果可能:String[Builder]在内部声明,而不在外部使用

相关问题