我正在使用Spark 2.2/2.3
中的Scala
通过Spark SQL和Scala Dataset/Dataframe
集合API(地图,过滤器等)来处理大量的CSV文件。
我目前发现我的开发笔记本电脑上的Spark大大超过了spark.executor.memory
(8 GB)设置的内存限制。运行驱动程序/执行器的JVM的内存使用量最多可增加约16 GB的堆使用量(执行期间通过jvisualvm进行观察,请参见下图)。 linux htop的峰值显示为〜16.6 GB RES和21.8 GB VIRT内存使用。在生产系统上,使用相同的spark配置,该过程似乎可以获取更多的内存(据称约为33GB)。
在执行过程中,我使用Spark Web UI看了执行器内存的使用情况-我看到了12.2GB / 8.8GB执行器内存(在生产中,UI处于关闭状态)之类的东西。
我知道实际的执行者内存限制不仅取决于spark.executor.memory配置,还取决于一些其他的提琴手因素,这些因素解释了额外的0.8 GB的执行者内存。据我所知,该驱动程序还需要内存,默认情况下它需要约1GB的内存。
但是,更重要的是,在执行驱动程序以释放未使用的数据集时我该怎么办?
示例:
fa
,fb
读取到数据集dsA, dsB
中。 dsA, dsB
=> dsA1, dsB1
进行一些过滤和映射。dsA1 & dsB1.persist(MEMORY_AND_DISK)
以避免重新读取和重新处理。dsA1
和dsB1
来创建dsAB2
。 dsAB2.persist(MEMORY_AND_DISK)
dsAB2
=>假设:现在,我可以“删除” dsA, dsB, dsA1
和dsB1
来释放它们使用的内存。
我打电话给
dsA1.unpersist(true); dsA1= null; dsA= null
dsB1.unpersist(true); dsB1= null; dsB= null
现在,垃圾收集器应该释放出数据集使用的部分GB数据。但是,即使在用System.getRuntime().gc()
修饰GC之后,在用jvisualvm进行观察时,我也看不到JVM堆内存使用率没有明显变化。
是否有任何技巧可以真正丢弃未使用的数据集/数据帧?