2008年9月25日星期四

escape analysis 和 lock elision

Escape analysis 是检查所有引用的作用域, 如果一个引用只是在一个本地作用域内,没有escape到更大的作用域, JIT编译成本地代码的时候会进行实时优化。
比如最重要的一个就是锁擦除 lock elision.
如果escape analysis发觉这个引用只在一个本地作用域(局部变量),这表示只有在当前作用域的线程才有可能访问这个锁,在这种情况下永远不可能有别的线程进入这个作用域和当前线程竞争,所以这种情况下这个锁可以被消除,这就是lock elision.

比如这段代码:
public String concatBuffer(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}

这种情况下StringBuffer对象的作用域就这这个方法内,所以StringBuffer完全没有必要线程安全加锁(当然更好的做法是用StringBuilder,不要依赖于聪明但是有时候行为不可预料的编译器和JIT/JRE.), 所以escape analysis结果表示可以优化,lock elision这种情况下就可以发生。

以下是测试程序
package test.thread;

public class LockElisionTest {

public static void main(String[] args) {
long t1 = System.currentTimeMillis();
LockElisionTest obj = new LockElisionTest();
for (int i = 0; i < 10000000; i++) {
obj.concatBuffer("1", "2");
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
}

public String concatBuffer(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}
}


注意的是是-XX:+DoEscapeAnalysis默认没有打开,而且你需要用-server模式

结果JRE5没有打开escape analysis是3500毫秒
JRE6打开是2100毫秒,关闭2200毫秒左右(估计因为还有别的优化)

没有评论: