me/JFR/3_Event采集详细配置.md

3.1 KiB
Raw Blame History

JFR 相关 Event

一共4个 Event但是需要关心的就下面这两个在 default.jfc 中默认是启用的。

  • Data Loss发生数据丢失时记录包括
    • 开始时间
    • Amount本次丢失多少事件
    • Total一共丢失多少事件
  • Recording Setting每次产生新的 Data Chunk 的时候,采集一次所有的 Event 的详细配置,记录到这个 Event 中

JAVA 应用相关 Event

1、Thread Local Allocation BufferTLAB

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。或者查看造成这些事件的热点堆栈是哪里然后优化代码。示例打开配置

<event name="jdk.ObjectAllocationInNewTLAB">
  <setting name="enabled">true</setting>
  <setting name="stackTrace">true</setting>
</event>

<event name="jdk.ObjectAllocationOutsideTLAB">
  <setting name="enabled">true</setting>
  <setting name="stackTrace">true</setting>
</event>