Python 重写数据帧变量时引发内存泄漏
我在spark驱动程序中遇到了内存泄漏,我似乎不知道为什么。我猜这与试图覆盖Python 重写数据帧变量时引发内存泄漏,python,apache-spark,memory-leaks,pyspark,apache-spark-sql,Python,Apache Spark,Memory Leaks,Pyspark,Apache Spark Sql,我在spark驱动程序中遇到了内存泄漏,我似乎不知道为什么。我猜这与试图覆盖DataFrame变量有关,但我找不到任何文档或其他类似问题 这是在Spark 2.1.0(PySpark)上实现的 从pyspark.sql导入SparkSession 从pyspark.sql导入SQLContext 从pyspark.sql.types导入* 火花=火花会话\ 建筑商先生\ .appName(“火花泄漏”)\ .getOrCreate() sc=spark.sparkContext sqlConte
DataFrame
变量有关,但我找不到任何文档或其他类似问题
这是在Spark 2.1.0(PySpark)上实现的
从pyspark.sql导入SparkSession
从pyspark.sql导入SQLContext
从pyspark.sql.types导入*
火花=火花会话\
建筑商先生\
.appName(“火花泄漏”)\
.getOrCreate()
sc=spark.sparkContext
sqlContext=sqlContext.getOrCreate(sc)
项目=5000000
数据=[str(x)表示范围内的x(1,项)]
df=sqlContext.createDataFrame(数据,StringType())
打印(df.count())
对于范围内的x(0,项):
sub_df=sqlContext.createDataFrame([str(x)],StringType()
df=df.减法(sub_df)
打印(df.count())
这将继续运行,直到驱动程序内存耗尽然后死亡
java.net.SocketException:连接重置
位于java.net.SocketInputStream.read(SocketInputStream.java:210)
位于java.net.SocketInputStream.read(SocketInputStream.java:141)
位于java.net.SocketInputStream.read(SocketInputStream.java:224)
位于org.apache.spark.api.python.pythonacumeratorv2.merge(PythonRDD.scala:917)
位于org.apache.spark.scheduler.DAGScheduler$$anonfun$updateacumerators$1.apply(DAGScheduler.scala:1089)
位于org.apache.spark.scheduler.DAGScheduler$$anonfun$updateacumerators$1.apply(DAGScheduler.scala:1081)
位于scala.collection.mutable.resizeblearray$class.foreach(resizeblearray.scala:59)
位于scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
位于org.apache.spark.scheduler.DAGScheduler.updateacumerators(DAGScheduler.scala:1081)
位于org.apache.spark.scheduler.DAGScheduler.handleTaskCompletion(DAGScheduler.scala:1184)
位于org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.doOnReceive(DAGScheduler.scala:1717)
位于org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:1675)
位于org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:1664)
位于org.apache.spark.util.EventLoop$$anon$1.run(EventLoop.scala:48)
17/05/25 16:55:40错误:无法更新任务13的累加器
java.net.SocketException:管道断开(写入失败)
位于java.net.SocketOutputStream.socketWrite0(本机方法)
位于java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
位于java.net.SocketOutputStream.write(SocketOutputStream.java:155)
位于java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
位于java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
位于java.io.DataOutputStream.flush(DataOutputStream.java:123)
位于org.apache.spark.api.python.pythonacumeratorv2.merge(PythonRDD.scala:915)
位于org.apache.spark.scheduler.DAGScheduler$$anonfun$updateacumerators$1.apply(DAGScheduler.scala:1089)
位于org.apache.spark.scheduler.DAGScheduler$$anonfun$updateacumerators$1.apply(DAGScheduler.scala:1081)
位于scala.collection.mutable.resizeblearray$class.foreach(resizeblearray.scala:59)
位于scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
位于org.apache.spark.scheduler.DAGScheduler.updateacumerators(DAGScheduler.scala:1081)
位于org.apache.spark.scheduler.DAGScheduler.handleTaskCompletion(DAGScheduler.scala:1184)
位于org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.doOnReceive(DAGScheduler.scala:1717)
位于org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:1675)
位于org.apache.spark.scheduler.DAGSchedulerEventProcessLoop.onReceive(DAGScheduler.scala:1664)
位于org.apache.spark.util.EventLoop$$anon$1.run(EventLoop.scala:48)
...
如果有什么区别的话,我认为内存应该收缩,因为项目正在从数据帧中删除,但事实并非如此
我不明白spark是如何将DataFrames
分配给Python变量之类的吗
我还尝试将df.subtract
分配给一个新的临时变量,然后取消持久化df
,然后将临时变量分配给df
,取消持久化临时变量,但这也有同样的问题。这里的基本问题似乎是理解数据帧的确切含义(这也适用于SparkRDD
)。本地DataFrame
对象有效地描述了在给定对象上执行某些操作时要执行的计算
因此,它是一个递归结构,它捕获了它的所有依赖项。在每次迭代中有效地执行计划。虽然Spark提供了一些工具,如检查点,,可以用来解决这个问题并切断沿袭,但问题中的代码一开始就没有多大意义
Spark中可用的分布式数据结构是为高延迟、IO密集型作业而设计的。将单个对象并行化,在数百万个分布式对象上执行数百万个Spark作业无法很好地工作
此外,Spark并不是为高效的单项目操作而设计的。每个减法都是O(N),形成一个完整的过程O(N2),在任何大型数据集上实际上都是无用的
虽然很琐碎,但正确的方法是这样的:
items = 5000000
df1 = spark.range(items).selectExpr("cast(id as string)")
df2 = spark.range(items).selectExpr("cast(id as string)")
df1.subtract(df2)