memory management in apache spark

这个talk依次从整个memory between execution and storage,memory across task的角度和memory across operators running within the same task的角度分析了spark如何使用内存。同时简单介绍了project tungsten

how to arbitrate memory between execution and storage?

首先普及一下基本概念。spark有两种memory

  • Execution memory: used for shuffles joins sorts and aggregations(特点,生成周期短,如果你的数据计算完并且被消费后就可以释放)
  • storage memory: used to cache data that will be reused later

从spark 1.6开始使用unified memory management策略,execution和storage的区域并没有完全严格划分,这样可以更好的利用内存资源

2017-01-17-182518

当内存用满时,spark会将storage的旧数据写进磁盘:

  • 为什么存storage的数据而不是execution:因为execution的数据一定在后面会被使用,而cache的数据不一定
  • 如果有应用依赖cache怎么办,比如machine learning的应用:解决方法是可以指定一部分数据不被换出内存

how to arbitrate memory across tasks running in parallel

按照任务数量动态的划分,比如有两个时就划分两个slot每个task一个,如果有新的任务提交,就再重新均分整个任务。如果有任务成为last one,他可以直接获得所有内存

how to arbitrate memory across operators running within the same task

这个问题结合一下例子来说明

2017-01-17-204355

  • 解决方法1,对于内存敏感的operator每个都分配一小块内存(在例子中是一个page)。简单但是低效的方法
  • 解决方法2, cooperative spilling。动态的调整每个Operator的内存直到动态平衡,这个是1.6以后的实现方式

project tungsten

binary in-memory data representation

长度不变的类型数据直接放入bitmap,variable data先写offset 然后写实际的数据

  • 相比object可以节省内存
  • 可以避免序列化和反序列化

cache-aware computation

2017-01-17-200122

比如这个例子,对于前者每次compare都需要通过指针去随机的访问key,而后面这个key和指针很近,一定程度上可以避免随机访问,更有利于数据缓存在内存中

code generation

这个是talk里面没讲的,我查了一些资料。code generation主要想法是通过在运行期间优化那些拖慢整个查询的代码到一个单独的函数中,消除虚拟函数的调用以及利用CPU寄存器来存放那些中间数据。(whole-stage code generation)。另外可以通过一些向量化的方式来提高效率。具体可以见SPARK-12795(whole-stage code generation)和SPARK-12992(vectorization)。

off-heap memory

  • 1.6开始execution可以使用off-heap memory
  • 2.0开始storage可以使用off-heap memory

off-heap memory最大的好处是避免gc,其他一些好处是memory sharing, zero copy I/O,dynamic allocation

ppt请见:http://www.slideshare.net/databricks/memory-management-in-apache-spark


本文采用创作共用保留署名-非商业-禁止演绎4.0国际许可证,欢迎转载,但转载请注明来自http://thousandhu.github.io,并保持转载后文章内容的完整。本人保留所有版权相关权利。

本文链接:http://thousandhu.github.io/2017/01/17/memory-management-in-apache-spark/