Spark 从 0 到 1 学习(10) —— Spark 调优(三)——内存调优

1. 内存调优

在这里插入图片描述

JVM 堆内存分为一块较大的 Eden 和两块较小的 Survivor。每次只使用 Eden 和其中一块 Survivor。当回收时 将 Eden 和 Survivor 中还存活IDE对象复制到 另外一块 Survivor 上,最后清理掉 Eden 和刚才使用过的 Survivor。也就是说当task创建出来对象会首先往 Eden 和 Survivor1 中存放,Survivor2 是空闲的,当 Eden 和Survivor1 区域放满以后就会触发 minor gc 小型垃圾回收,清理掉不再使用的对象。会将存活下来的对象放入Survivor2 中。

如果存活下来的对象大小大于 Survivor2 的大小,那么JVM就会将多余的对象直接放入到老年代中。

如果这个时候年轻代的内存不是很大的话,就会经常的进行 minor gc,频繁的minor gc会导致短时间内有些存活的对象(多次垃圾回收都没有回收掉,一直在用的又不能被释放,这种对象每经过一次minor gc都存活下来)频繁的倒来倒去,会导致这些短生命周期的对象(不一定长期使用)每进行一次垃圾回收就会长一岁。年龄过大,默认15岁,垃圾回收还是没有回收回去就会跑到老年代里面去了。

这样会导致在老年代中存放大量的短生命周期的对象,老年代应该存放的是数量比较少并且会长期使用的对象,比如数据库连接池对象。这样的话,老年代就会满溢(full gc 因为本来老年代中的对象很少,很少进行full gc 因此采取了不太复杂但是消耗性能和时间的垃圾回收算法)。不管minor gc 还是 full gc都会导致JVM的工作线程停止。

总结-堆内存不足造成的影响:

  • 频繁的 minor GC。
  • 老年代中大量的短生命周期的对象,导致 full GC。
  • GC 多了会影响 Spark的性能和运行的速度。

Spark JVM 调优主要是降低 GC 时间,可以修改 Executor 内存比例参数。

RDD 缓存、task 定义的运行的算子函数,可能会创建很多对象,这样会占用大量的堆内存。对内存满了之后会频繁的 GC。如果 GC 还不能满足内存的需要的话就会报 OOM。

比如一个 task 在运行的时候创建 N 个对象,这些对象首先要放入到 JVM 年轻带中。

比如在存数据的时候我们使用了 foreach 来讲数据写入到内存,每条数据都会封装到一个对象存入数据库中,那么有多少条数据就会在 JVM 中创建多少对象。

2. Spark 中如何内存调优?

Spark Executor 堆内存中存放(以静态内存管理为例):

  • RDD 的缓存数据和广播变量:

    spark.storage.memoryFraction 0.6

  • shuffle 聚合内存:

    spark.shuffle.memoryFraction 0.2

  • task 的运行内存:0.2

那么如何调优呢?

  1. 提高 Executor 总体内存的大小。
  2. 降低存储内存比例或者降低聚合内存比例。

3. 如何查看 GC?

Spark WEBUI 中 job -> stage -> task。

猜你喜欢

转载自blog.csdn.net/dwjf321/article/details/109056283
今日推荐