首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Apache Spark 内存管理详解(2)

Apache Spark 内存管理详解(2)

2 . 内存空间分配2.1 静态内存管理在 Spark 最初采用的静态内存管理机制下,存储内存、执行内存和其他内存的大小在 Spark                应用程序运行期间均为固定的,但用户可以应用程序启动前进行配置,堆内内存的分配如图 2 所示:
图 2 .                    静态内存管理图示——堆内可以看到,可用的堆内内存的大小需要按照下面的方式计算:
清单 2 .                可用堆内内存空间
1
2
可用的存储内存 = systemMaxMemory * spark.storage.memoryFraction * spark.storage.safetyFraction
可用的执行内存 = systemMaxMemory * spark.shuffle.memoryFraction * spark.shuffle.safetyFraction




其中 systemMaxMemory 取决于当前 JVM 堆内内存的大小,最后可用的执行内存或者存储内存要在此基础上与各自的                memoryFraction 参数和 safetyFraction 参数相乘得出。上述计算公式中的两个 safetyFraction                参数,其意义在于在逻辑上预留出 1-safetyFraction 这么一块保险区域,降低因实际内存超出当前预设范围而导致 OOM                的风险(上文提到,对于非序列化对象的内存采样估算会产生误差)。值得注意的是,这个预留的保险区域仅仅是一种逻辑上的规划,在具体使用时 Spark                并没有区别对待,和"其它内存"一样交给了 JVM 去管理。
堆外的空间分配较为简单,只有存储内存和执行内存,如图 3 所示。可用的执行内存和存储内存占用的空间大小直接由参数                spark.memory.storageFraction 决定,由于堆外内存占用的空间可以被精确计算,所以无需再设定保险区域。
图 3 .                    静态内存管理图示——堆外 静态内存管理机制实现起来较为简单,但如果用户不熟悉 Spark                的存储机制,或没有根据具体的数据规模和计算任务或做相应的配置,很容易造成"一半海水,一半火焰"的局面,即存储内存和执行内存中的一方剩余大量的空间,而另一方却早早被占满,不得不淘汰或移出旧的内容以存储新的内容。由于新的内存管理机制的出现,这种方式目前已经很少有开发者使用,出于兼容旧版本的应用程序的目的,Spark                仍然保留了它的实现。
2.2 统一内存管理Spark 1.6 之后引入的统一内存管理机制,与静态内存管理的区别在于存储内存和执行内存共享同一块空间,可以动态占用对方的空闲区域,如图 4 和图                5 所示
图 4 .                    统一内存管理图示——堆内图 5 .                    统一内存管理图示——堆外其中最重要的优化在于动态占用机制,其规则如下:
  • 设定基本的存储内存和执行内存区域(spark.storage.storageFraction                    参数),该设定确定了双方各自拥有的空间的范围
  • 双方的空间都不足时,则存储到硬盘;若己方空间不足而对方空余时,可借用对方的空间;(存储空间不足是指不足以放下一个完整的                    Block)
  • 执行内存的空间被对方占用后,可让对方将占用的部分转存到硬盘,然后"归还"借用的空间
  • 存储内存的空间被对方占用后,无法让对方"归还",因为需要考虑 Shuffle                    过程中的很多因素,实现起来较为复杂[4]
图 6 . 动态占用机制图示 凭借统一内存管理机制,Spark 在一定程度上提高了堆内和堆外内存资源的利用率,降低了开发者维护 Spark                内存的难度,但并不意味着开发者可以高枕无忧。譬如,所以如果存储内存的空间太大或者说缓存的数据过多,反而会导致频繁的全量垃圾回收,降低任务执行时的性能,因为缓存的                RDD 数据通常都是长期驻留内存的 [5] 。所以要想充分发挥 Spark                的性能,需要开发者进一步了解存储内存和执行内存各自的管理方式和实现原理。
返回列表