### JFR 相关 Event
一共4个 Event,但是需要关心的就下面这两个,在 default.jfc 中默认是启用的。
- Data Loss:发生数据丢失时记录,包括:
+ 开始时间
+ Amount:本次丢失多少事件
+ Total:一共丢失多少事件
- Recording Setting:每次产生新的 Data Chunk 的时候,采集一次所有的 Event 的详细配置,记录到这个 Event 中
### JAVA 应用相关 Event
##### 1、Thread Local Allocation Buffer(TLAB)
TLAB 目的是为了快速分配内存。堆内存是线程共享的,所以在堆内存直接分配对象,就会锁定整个堆,这样效率太低。TLAB 是位于堆内存的一块内存区域,在为每个线程分配 TLAB 的时候才会锁定堆(G1 是 CAS 分配)。这样一来,每个线程在分配对象的时候,优先从 TLAB 上分配。大对象的分配不会发生在 TLAB,将会涉及到线程同步。这是比较笼统的看法,G1 的情况更加复杂。为了能说明 JFR 相关事件的意义,这里继续深入一下关于 G1 TLAB 相关原理。创建一个对象时:
- 首先尝试从线程现有的TLAB空间分配内存
- 如果剩余空间不足,查看是否能分配一个新的TLAB,再分配内存给对象。每个线程的 TLAB 大小是随着线程运行不断变化的。TLAB 的内部,每个线程维护着一个*refill_waste*的变量,这个变量的值,决定是否能分配一个新的TLAB。
- 当 TLAB 剩余空间不足时,查看当前 TLAB 的剩余大小
+ 如果小于*refill_waste*则需要分配一个新的TLAB,这时候,JFR 会产生一条*ObjectAllocationInNewTLAB*记录
+ 否则认为这个 TLAB 还不算满,当前这个对象将直接走堆上内存分配,这时会产生一条*ObjectAllocationOutsideTLAB*记录
*ObjectAllocationInNewTLAB*在 default.jfc 中默认关闭,可以通过向导配置*memory-profiling*调为*memory-profiling-enabled-medium*打开。也可以用高级配置这个 Event 是否采集,以及堆栈是否采集。采集内容包括:时间、线程、本次需要分配内存大小、对象类型、当前 TLAB 大小。
*ObjectAllocationOutsideTLAB*在 default.jfc 中也是默认关闭的,可以通过向导配置*memory-profiling*调为*memory-profiling-enabled-medium*打开。也可以用高级配置这个 Event 是否采集,以及堆栈是否采集。采集内容包括:时间、线程、本次需要分配内存大小、对象类型。
**这两个的采集,对性能影响比较大,不能长期跑。尤其是在启用堆栈收集后,影响就更大了。一般考虑动态打开。**如果需要定位大对象分配代码位置,可以采集一个时间段的*ObjectAllocationOutsideTLAB*查看最大需要的内存大小是多少,通过减少内存分配来减少GC。或者查看造成这些事件的热点堆栈是哪里,然后优化代码。示例打开配置:
```xml
true
true
true
true
```