spark 内存管理和内存计算示例

image.png

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(经常操作)

image.png
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 内存抢占

image.png
内存抢占规则: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
image.png
image.png
计算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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值