1 堆外内存
1.1 spark.memory.offHeap.size(基本不操作)
不在 JVM 内申请内存,而是调用 Java 的 unsafe 相关 API 进行诸如 C 语言里面的 malloc() 直接向操作系统申请内存,由于这种方式不经过 JVM 内存管理,所以可以避免频繁的 GC,这种内存申请的缺点是必须自己编写内存申请和释放的逻辑。
主要是为了支持Tungsten项目,Tungsten项目致力于提升Spark程序对内存和CPU的利用率,使性能达到硬件的极限。
1.2 spark.executor.pyspark.memory(基本不操作)
用来对pyspark的executor内存进行限制,主要用于执行python上编写的UDF
1.3 spark.executor.memoryOverhead(偶尔操作)
在 YARN,K8S 部署模式下,container 会预留一部分内存,形式是堆外,用来保证稳定性,主要用于创建Java Object时的额外开销,Native方法调用,线程栈, NIO Buffer等
由 spark.executor.memoryOverhead 参数指定,默认大小为 executorMemory * 0.10, with minimum of 384m
2 堆内内存
2.1 spark.executor.memory(经常操作)
jvm堆内内存分成四部分:
- **reservedMemory(预留内存):**预留内存300M,用于保障spark正常运行;如果Executor分配的内存小于 1.5 * 300 = 450M 时,Executor将无法执行
- **user/other memory(用户/其他内存): **用于spark内部的一些元数据、用户的数据结构、防止在稀疏和异常大的记录的情况下出现对内存估计不足导致oom时的内存缓冲。(spark.executor.memory-300M)*(1-spark.memory.fraction)
- **execution(执行内存):**用于spark的计算:shuffle、sort、agg等这些计算时会用到的内存。(spark.executor.memory-300M)(1-spark.memory.fraction)(1-spark.memory.storageFraction)
- **storage(存储内存):**主要用于rdd的缓存。(spark.executor.memory-300M)*(1-spark.memory.fraction)*spark.memory.storageFraction
spark.memory.fraction默认0.6
spark.memory.storageFraction默认0.5
2.2 内存抢占
内存抢占规则:Execution Memory 和 Storage Memory 之间可以相互转化。转化规则,一共可以总结为 3 条:
- 如果对方的内存空间有空闲,双方可以互相抢占;
- 对于 Storage Memory 抢占的 Execution Memory 部分,当分布式任务有计算需要时,Storage Memory 必须立即归还抢占的内存,涉及的缓存数据要么落盘、要么清除;
- 对于 Execution Memory 抢占的 Storage Memory 部分,即便 Storage Memory 有收回内存的需要,也必须要等到分布式任务执行完毕才能释放。
内存计算示例
参数:
spark.executor.memory:2G
spark.memory.fraction:0.6
spark.memory.storageFraction:0.5
计算executor的内存:
spark.executor.memory = 2 GB
Java Heap Memory = 2 GB = 2048 MB
Reserved Memory = 300 MB
Usable Memory = 2048-300=1748 MB
User Memory = 1748*(1-0.6)=699.2 MB
Spark Memory = 1748*0.6 = 1048.8 MB
Spark Storage Memory = 1048.8*0.5=524.4 MB
Spark Execution Memory = 1048.8*(1-0.5)=524.4 MB
从spark UI上可以看到实际executor可用内存是912.3MB(Storage+Execution),而计算的结果是1048.8MB。
问题在于JVM分配的内存是Runtime.getRuntime.maxMemory,计算方式可以参考:jvm内存计算。计算后jvm内存是1820.4444MB
重新计算:
spark.executor.memory = 2 GB
Java Heap Memory = 1820.4444 MB
Reserved Memory = 300 MB
Usable Memory = 1820.4444-300=1520.4444 MB
User Memory = 1520.4444*(1-0.6)=609.18 MB
Spark Memory = 1520.4444*0.6 = 912.27 MB
Spark Storage Memory = 912.27*0.5=456.13 MB
Spark Execution Memory = 912.27*(1-0.5)=456.13 MB
参考链接:
https://zhuanlan.zhihu.com/p/608080538?utm_id=0
https://blog.csdn.net/yfkiss/article/details/83446678