`
blood
  • 浏览: 2176 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
社区版块
存档分类

由StringBuffer和StringBuilder感受JVM运行时编译优化(just in time)

    博客分类:
  • java
阅读更多

很多人习惯把线程安全的StringBuffer用做局部变量,依赖于JIT,不比StringBuilder慢。

 

 

StringBuffer虽然加了synchronized,做局部变量时,锁住的只是线程局部变量,没有锁竞争

类似于synchronized(new Object()),是没有意义的。

 

JVM运行一会就发现这个无意义的锁,可以被清除掉,就做“锁省略”优化.

再执行,无锁的StringBuffer性能就跟StringBuilder差不多了.

 

这个简单的近乎没有意义的测试(或者因为如此吧,被投了几个“新手贴”, 哈。。。),测的却是表面上看不到的优化

 

参考

JVM优化之逃逸分析(Escape Analysis) http://www.iteye.com/topic/473355

Mustang 中的同步优化 http://www.ibm.com/developerworks/cn/java/j-jtp10185/

        再谈 Urban 性能传言    http://www.ibm.com/developerworks/cn/java/j-jtp09275.html

 

    public void test() throws Exception {
        int total = 11000000;
        
        for (int x = 0; x < 100; x++) {

            StringBuffer sb1 = new StringBuffer(total);
            long start = System.currentTimeMillis();
            for (int i = 0; i < total; i++) {
                sb1.append(1);
            }
            long sb1Time = System.currentTimeMillis() - start;

            StringBuilder sb2 = new StringBuilder(total);
            start = System.currentTimeMillis();
            for (int i = 0; i < total; i++) {
                sb2.append(1);
            }
            System.out.println(sb1Time + " " + (System.currentTimeMillis() - start));
            
        }
    }

 
   执行结果
688 203
688 219
688 219
703 203
687 203
218 218
218 218
218 203
219 219
219 219
219 203
.......
 

可以看到,前几次调用,StringBuffer比StringBuilder慢的多,执行几次之后,两者已经接近

 

 

分享到:
评论
19 楼 唯快不破 2010-05-14  
StringBuilder做局部变量放在线程栈内存中本来就是线程安全的啊,为何念念不忘StringBuffer
18 楼 freish 2010-05-14  
这个得看依赖于java语言规范,而不能依赖于某个jre,IBM的jre或者其他的jre都是这种表现么
17 楼 piao_bo_yi 2010-05-14  
8.13 Locks and Synchronization
There is a lock associated with every object. The Java programming language does not provide a way to perform separate lock and unlock operations; instead, they are implicitly performed by high-level constructs that always arrange to pair such operations correctly. (The Java virtual machine, however, provides separate monitorenter and monitorexit instructions that implement the lock and unlock operations.)
16 楼 caiceclb 2010-05-14  
<div class="quote_title">blood 写道</div>
<div class="quote_div">
<p> </p>
<p style="margin: 0px;">这个简单的近乎没有意义的测试(或者因为如此吧,被投了几个“新手贴”, 哈。。。)</p>
<p> </p>
</div>
<p> </p>
<p>就是说,你明知道是新手帖,还不往入门版发喽</p>
15 楼 J-catTeam 2010-05-14  
blood 写道
J-catTeam 写道
同步消耗的地方在于并发的时候。你一个线程。


无语。。。

这里测的不是多线程的锁竞争,而是要看出JIT的运行时编译优化,锁省略优化
诸如循环展开,方法内联等编译优化。






呵呵·是我考虑不周。我研究一下
14 楼 RednaxelaFX 2010-05-14  
请问楼主能否把测试用的完整代码以及完整的命令行启动参数、具体的JDK版本和平台情况标明?如果您只是在一个main()里调用了一次顶楼中的test()方法,那这个计时方式就比较不好了。
13 楼 sdh5724 2010-05-14  
-XX:+UseBiasedLocking
Enables a technique for improving the performance of uncontended synchronization. An object is "biased" toward the thread which first acquires its monitor via a monitorenter bytecode or synchronized method invocation; subsequent monitor-related operations performed by that thread are relatively much faster on multiprocessor machines. Some applications with significant amounts of uncontended synchronization may attain significant speedups with this flag enabled; some applications with certain patterns of locking may see slowdowns, though attempts have been made to minimize the negative impact.


注:  java5.0 下, 这个参数是关闭的。
虽然JIT 优化了非竞争同步, 但是, 程序员们不要依赖这个特定优化。 我相信JIT未必能100%做到这个事情。 特别是一些读共享的代码。 JIT就未必能意识到是不是需要同步。
这个优化对于一些老代码的的确非常有效, 我做过不少测试, 几乎是性能毫无下降。 但是新代码, 不需要使用同步的代码, 尽量不要。
12 楼 esanone 2010-05-13  
StringBuffer,用习惯了.呵呵
11 楼 blood 2010-05-13  
很多人因为习惯,或者老代码,都是用StringBuffer,还多是做局部变量。
当然用StringBuilder是更好的,但因为编译期优化的存在,也可以不用把老代码中的StringBuffer替换回来。
执行几次之后,JIT就会优化成跟StringBuilder接近的性能。




10 楼 blood 2010-05-13  
J-catTeam 写道
同步消耗的地方在于并发的时候。你一个线程。


无语。。。

这里测的不是多线程的锁竞争,而是要看出JIT的运行时编译优化,锁省略优化
诸如循环展开,方法内联等编译优化。





9 楼 J-catTeam 2010-05-13  
同步消耗的地方在于并发的时候。你一个线程。
8 楼 whaosoft 2010-05-13  
谢谢lz吧  又受教了。。 确实一般都用在 方法里 (也就是做局部变量)方法区本来就不是线程安全的 但非要用StringBuffer 这个线程安全的东西 也没吗用。。。 行以后改用StringBuilder
7 楼 leoizumi 2010-05-13  
理论上虽然快...但是,一般都是用StringBuffer ......
6 楼 blood 2010-05-13  
liu78778 写道
明显是猜的, 这也能叫分析


请了解一下JIT再来看是不是猜的吧
5 楼 liu78778 2010-05-13  
明显是猜的, 这也能叫分析
4 楼 csslisi 2010-05-13  
这个结论比较肤浅,像是猜的
3 楼 m7788 2010-05-13  
只能说jvm确实牛。
2 楼 shuiguozheng 2010-05-13  
x_root 写道
局部变量我一般都用StringBuilder.

      jvm 可以自动释放锁的啊?
1 楼 x_root 2010-05-13  
局部变量我一般都用StringBuilder.
Global site tag (gtag.js) - Google Analytics