1、spark内存模型理解
上一篇在内存模型理解部分描述不当,以下是我重新整理后的,有需要的可以琢磨琢磨,不管是日常任务调优,还是面试 总会起点作用吧:
jvm堆内的内存分为四个部分(spark.memory.fraction=0.6)
reservedMemory:预留内存300M,用于保障spark正常运行
other memory:用于spark内部的一些元数据、用户的数据结构、防止在稀疏和异常大的记录的情况下出现对内存估计不足导致oom时的内存缓冲;估算大小为3G(8G-300M)*0.4
execution:用于spark的计算:shuffle、sort、aggregation等这些计算时会用到的内存;估算大小为2.3G(8G-300M)*0.6*0.5
storage:主要用于rdd的缓存;2.3G(8G-300M)*0.6*0.5
execution与storage 两个模块可以互相借用空间(动态占用机制),但有个前提,就是对方有足够的空间(默认情况下各占 50%,由spark.memory.storageFraction参数决定,在这次任务中,各有2.3G的空间)
关于execution与storage 动态占用机制的理解(三种情况):
1、不使用缓存(storage)的应用程序可以将整个空间用于执行(execution),从而避免不必要的磁盘溢写。
2、storage 曾经向 execution 借了空间,它缓存的数据可能是非常的多,然后 execution 又不需要那么大的空间 ,假设现在 storage 占了 80%,execution 占了 20%,然后 execution 说自己空间不足,execution 会向内存管理器发信号把 Storgae 曾经占用的超过 50%数据的那部份强制挤掉 (注意:drop 后数据会不会丢失主要是看你在程序设置的 storage_level 来决定你是 Drop 到那里,可能 Drop 到磁盘上)(storage不足是指不足以放下一个完整的 Block)
3、execution 空间不足的情况下,除了选择向 storage 借空间以外,也可以把一部份数据 Spill 到磁盘上,但很多时候基于性能调优方面的考虑都不想把数据 Spill 到磁盘上,会优先选择向 storage 借空间。此时,正好storage有富裕空间,即storage实际占用不足 50% 的情况下,storage 会借空间给execution 。 假设现在 storage 占了 20%,execution 占了 80%。后面,storage发现自己空间不够用了,此时,只能等execution 释放空间,才能使用
因此,在这个案例中,有一些Broadcast的数据,但占比很小,可以认为计算内存execution 可用最大内存为4.6G
2、调参之后效果
最后,给大家一个我调过参数之后的图:
调了overhead内存后,alloc和used曲线离的更近了,说明总的mem内存浪费减少。
gc的时间也短了,之前是分钟级,现是秒级