【问题标题】:PySpark error java.lang.OutOfMemoryError: GC overhead limit exceededPySpark 错误 java.lang.OutOfMemoryError:超出 GC 开销限制
【发布时间】:2018-03-14 09:39:33
【问题描述】:

如何修复我的 GC overhead limit exceeded 在 PySpark 版本 2.2.1 中发生的问题。安装在 Ubuntu 16.04.4 上。

在 Python 3.5.2 脚本中,我将 spark 设置为:

 spark = SparkSession.builder.appName('achats_fusion_files').getOrCreate()                                                                                                                              
 spark.conf.set("spark.sql.pivotMaxValues", "1000000")                                                                                                                                                  
 spark.conf.set("spark.sql.autoBroadcastJoinThreshold", "-1")                                                                                                                                           
 spark.conf.set("spark.executor.memory", "1g")                                                                                                                                                          
 spark.conf.set("spark.driver.memory", "1g") 

如何使用 Python 脚本中的良好设置来解决问题?

下面的错误信息:

18/03/14 09:57:25 ERROR Executor: Exception in task 34.0 in stage 36.0 (TID 2076)                                                                                                                         
java.lang.OutOfMemoryError: GC overhead limit exceeded                                                                                                                                                     
    at java.util.regex.Pattern.compile(Pattern.java:1667)                                                                                                                                              
    at java.util.regex.Pattern.<init>(Pattern.java:1351)                                                                                                                                               
    at java.util.regex.Pattern.compile(Pattern.java:1028)                                                                                                                                              
    at org.apache.spark.network.util.JavaUtils.byteStringAs(JavaUtils.java:266)                                                                                                                        
    at org.apache.spark.network.util.JavaUtils.byteStringAsBytes(JavaUtils.java:302)                                                                                                                   
    at org.apache.spark.util.Utils$.byteStringAsBytes(Utils.scala:1087)                                                                                                                                
    at org.apache.spark.SparkConf.getSizeAsBytes(SparkConf.scala:310)                                                                                                                                  
    at org.apache.spark.io.LZ4CompressionCodec.compressedOutputStream(CompressionCodec.scala:114)                                                                                                      
    at org.apache.spark.serializer.SerializerManager.wrapForCompression(SerializerManager.scala:156)                                                                                                   
    at org.apache.spark.serializer.SerializerManager.wrapStream(SerializerManager.scala:131)                                                                                                           
    at org.apache.spark.storage.DiskBlockObjectWriter.open(DiskBlockObjectWriter.scala:120)                                                                                                            
    at org.apache.spark.storage.DiskBlockObjectWriter.write(DiskBlockObjectWriter.scala:237)                                                                                                           
    at org.apache.spark.shuffle.sort.BypassMergeSortShuffleWriter.write(BypassMergeSortShuffleWriter.java:151)                                                                                         
    at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:96)                                                                                                                      
    at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:53)                                                                                                                      
    at org.apache.spark.scheduler.Task.run(Task.scala:108)                                                                                                                                             
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:338)                                                                                                                           
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)                                                                                                                 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)                                                                                                                 
    at java.lang.Thread.run(Thread.java:748)                               

【问题讨论】:

    标签: pyspark


    【解决方案1】:

    直接从文档中获取,

    • GC 调优的第一步是收集有关垃圾收集发生频率和 GC 时间量的统计信息。这可以通过在 Java 选项中添加 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 来完成。
    • Spark 中 GC 调优的目标是确保只有长寿命的 RDD 存储在老年代,而年轻一代的大小足以存储短寿命的对象。这将有助于避免完全 GC 收集任务执行期间创建的临时对象。
    • 通过收集 GC 统计信息检查是否有太多垃圾收集。如果在任务完成之前多次调用完整 GC,则意味着没有足够的内存可用于执行任务。
    • 如果次要收集太多但主要 GC 不多,则为 Eden 分配更多内存会有所帮助。您可以将 Eden 的大小设置为高估每个任务需要多少内存。如果确定 Eden 的大小为 E,则可以使用选项 -Xmn=4/3*E 设置年轻代的大小。 (扩大 4/3 也是为了考虑幸存区域使用的空间。)
    • 在打印的 GC 统计信息中,如果 OldGen 快满了,通过降低 spark.memory.fraction 来减少用于缓存的内存量;缓存更少的对象比减慢任务执行速度要好。或者,考虑减小年轻代的大小。这意味着如果您已按上述方式设置 -Xmn,则降低它。如果不是,请尝试更改 JVM 的 NewRatio 参数的值。许多 JVM 默认为 2,这意味着老年代占据了堆的 2/3。它应该足够大,以至于这个分数超过 spark.memory.fraction。
    • 使用 -XX:+UseG1GC 尝试 G1GC 垃圾收集器。在垃圾收集成为瓶颈的某些情况下,它可以提高性能。 (这对我有帮助)

    其他一些对我有帮助的参数是,

    • -XX:ConcGCThreads=20
    • -XX:InitiatingHeapOcuupancyPercent=35

    可以通过在作业的配置中设置 spark.executor.extraJavaOptions 来指定执行器的所有 GC 调整标志。

    查看this 了解更多详情。

    编辑:

    在你的 spark-defaults.conf 中写,

    spark.executor.JavaOptions -XX:+UseG1GC

    spark.executor.extraJavaOptions -XX:ConcGCThreads=20 -XX:InitiatingHeapOcuupancyPercent=35

    【讨论】:

    • 感谢您的回答。对不起,我对 Java 一无所知。如果可能的话,请您提供一个如何在 python 脚本中使用此设置的示例?
    • 谢谢!我做了cp SPARK_HOME/conf/spark-defaults.conf.template SPARK_HOME/conf/spark-defaults.conf 并添加了这个配置
    • -XX:InitiatingHeapOcuupancyPercent=35 中有错字。应该是:-XX:InitiatingHeapOcupancyPercent=35多了一个u
    猜你喜欢
    • 2020-07-24
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    • 2021-01-07
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    相关资源
    最近更新 更多