本文是何适 JVM 修仙系列第 5 篇,文末有本系列文章汇总。
上一篇介绍的栈上分配,这篇介绍一个容易跟栈上分配混淆的 TLAB 上分配。
Java 程序会极其频繁的创建对象并为对象分配内存空间,一般情况下对象是分配在堆上的,堆又是全局共享的,所以会存在这样一个问题:多个线程同时在堆上申请空间,而堆要同步处理,导致性能下降。
为了解决这个问题,Java 虚拟机提供了 TLAB 分配。TLAB 全称是 Thread Local Allocation Buffer,线程本地分配缓存,是一个线程私有的内存分配区域。
虚拟机在 eden 区为每一个线程分配一块线程专用的内存区域 TLAB 区域。这样多个线程同时在堆上申请空间时,可以直接在当前线程自己的 TLAB 区域分配对象,不必等待堆同步处理,提高了效率。
设置参数:-XX:+UseTLAB:打开 TLAB(默认是开启的)。
TLAB 空间的内存非常小,默认情况下仅占有整个 Eden 空间的 1%,当然可以通过选项-XX:TLABWasteTargetPercent 设置 TLAB 空间所占用 Eden 空间的百分比大小。
如下代码,记录分配 100000000 个 byte 数组对象花费的时间:
public class TLABTest {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
byte[] b = new byte[2];
b[0] = 1;
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
}
设置如下参数,开启 TLAB,花费时间 527ms
-XX:+UseTLAB -XX:-DoEscapeAnalysis -server
-XX:+UseTLAB:开启TLAB
-XX:-DoEscapeAnalysis:禁用逃逸分析,避免栈上分配的影响
设置如下参数,关闭 TLAB,花费时间 1166ms
-XX:-UseTLAB -XX:-DoEscapeAnalysis -server
-XX:-UseTLAB:关闭TLAB
-XX:-DoEscapeAnalysis:禁用逃逸分析,避免栈上分配的影响
优先级排序:栈上分配 > TLAB 上分配 > eden 区 > 老年代
栈上分配 VS TLAB 上分配