PySpark错误java.lang.OutOfMemoryError:超出了GC开销限制

时间:2018-03-14 09:39:34

标签: pyspark

如何修复PySpark 2.2.1版本中GC overhead limit exceeded的问题。安装在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)                               

1 个答案:

答案 0 :(得分:2)

直接从文档中获取,

  • GC调整的第一步是收集有关垃圾收集发生频率和GC使用时间的统计信息。这可以通过将-verbose:gc -XX:+ PrintGCDetails -XX:+ PrintGCTimeStamps添加到Java选项来完成。
  • Spark中GC调整的目标是确保只有长期存在的RDD存储在Old代中,并且Young代的大小足以存储短期对象。这将有助于避免完整的GC收集在任务执行期间创建的临时对象。
  • 通过收集GC统计数据来检查是否有太多垃圾收集。如果在任务完成之前多次调用完整的GC,则意味着没有足够的内存可用于执行任务。
  • 如果有太多次要集合但没有多少主要GC,为Eden分配更多内存会有所帮助。您可以将Eden的大小设置为高估每个任务所需的内存量。如果确定Eden的大小为E,则可以使用选项-Xmn = 4/3 * E设置Young代的大小。 (按比例增加4/3是为了考虑幸存者地区使用的空间。)
  • 在打印的GC统计信息中,如果OldGen接近满,则通过降低spark.memory.fraction来减少用于缓存的内存量;缓存更少的对象比减慢任务执行速度更好。或者,考虑减小Young代的尺寸。这意味着如果您按上述设置降低-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