Spark应用Executor内存指标疑问:JVMHeapMemory等堆内指标差异求解
Spark ExecutorMetrics内存指标含义及偏差原因
各指标具体含义
- JVMHeapMemory:JVM进程当前已使用的堆内存总量,覆盖Spark统一管控内存、用户自定义代码占用内存、JVM自身对象开销、未回收垃圾对象等所有堆内内存占用,属于全堆已用内存的实时统计值。
- OnHeapExecutionMemory:堆内用于执行计算(shuffle、join、排序、聚合等操作)的内存峰值,仅统计Spark统一内存管理器分配给执行任务的堆内内存部分。
- OnHeapStorageMemory:堆内用于数据缓存(RDD缓存、广播变量、分布式表缓存等)的内存峰值,仅统计Spark统一内存管理器分配给存储模块的堆内内存部分。
- OnHeapUnifiedMemory:堆内统一内存的总使用峰值,等于同一时间点的
OnHeapExecutionMemory+OnHeapStorageMemory之和,统一内存区域是Spark内部可在执行和存储之间动态抢占的内存区间。
偏差产生原因
1. 公式适用场景错误
你提到的JVM On Heap memory = OnHeapExecutionMemory + OnHeapStorageMemory + 预留内存 + 用户内存是Spark启动时对分配给Executor/Driver的最大堆内存配置的拆分逻辑,是容量上限的拆分规则,不是实时已使用内存的计算公式。你采集到的JVMHeapMemory是当前已使用的堆内存,而几个ExecutorMetrics统计的是Spark统一管理区域内的已使用峰值,二者统计范畴完全不同。
2. 统计范畴差异
你采集到的OnHeapExecutionMemory为0,说明到采样时间点为止,该进程还没有触发过堆内执行内存的占用,OnHeapStorageMemory仅约561KB,也仅存储了少量缓存数据,二者加和仅代表统一内存区域的已使用量,除此之外JVM堆内存还包含不会被统计到OnHeap系列指标的部分:
- 用户自定义代码创建的对象占用的用户内存区域,这部分内存Spark不做统一管控
- JVM内部元数据、类对象、加载Jar包的相关对象等基础开销
- 还未被GC回收的垃圾对象
- Spark内部框架运行产生的非执行、非存储类的对象开销
同时你采集的是Driver端的指标,Driver本身通常不会运行大量执行计算任务,执行内存为0属于常见情况,Driver的堆内存更多用来存储DAG调度信息、任务元数据、Driver端运行的用户代码对象等,这些都不会计入执行、存储相关指标,偏差会更明显。
3. 峰值统计的时间差问题
虽然官方标注这几个Execution、Storage类指标是峰值,但峰值统计窗口和采样时间可能存在错位:你采样的时间点JVMHeapMemory是当前已使用值,而OnHeap系列的峰值可能出现在更早的时间点,之后内存被回收后峰值统计不会回退,或是反过来当前JVM已用堆内存很高,但执行和存储的峰值还未达到最高值,也会产生数值偏差。
内容的提问来源于stack exchange,提问作者Software Enthusiast
相关产品推荐
相关产品推荐

