这是我从Spark shell运行的工作:
val l = sc.parallelize((1 to 5000000).toList)
val m = l.map(m => m*23)
m.take(5000000)
工人似乎是"加载"州:
什么是"加载"国家?
更新:
据我所知take
将在群集上执行作业,然后将结果返回给Driver。所以"加载" state等于加载到驱动程序的数据?
答案 0 :(得分:2)
我相信如果你这样做,
(1 to 5000000 ).toList
您一定会遇到java.lang.OutOfMemoryError: GC overhead limit exceeded
。
当JVM意识到它在Grabage Collection
中花费了太多时间时会发生这种情况。默认情况下,如果您在more than 98% of the total time
中花费GC
并在GC
的{{1}} less than 2%
恢复后,JVM配置为抛出此错误。
在这种特殊情况下,您为每次迭代创建heap
new instance
(List
,因此每次返回immutability
new instance
时都是如此。这意味着每次迭代都会留下无用的List
实例,对于大小为数百万的List
,会占用大量内存并频繁触发List
。此外,每次GC
都必须释放大量内存,因此需要花费大量时间。
这最终导致错误 - GC
。
如果不存在会怎么样? - >这意味着能够清洁的少量GC将再次快速填充,从而迫使GC再次重新启动清洁过程。这形成了一个恶性循环,其中CPU 100%忙于GC并且无法进行实际工作。应用程序将面临极端减速 - 过去以毫秒为单位完成的操作现在可能需要几分钟才能完成。
这是JVM中实施的先发制人的快速安全保护措施。
您可以使用以下Java选项禁用此安全措施。
java.lang.OutOfMemoryError: GC overhead limit exceeded
但我强烈建议 NOT 这样做。
即使您禁用此功能(或者如果您的Spark-Cluster通过分配大堆空间来避免此-XX:-UseGCOverheadLimit
),也可以使用
to some extent
需要很长时间。
此外,我强烈认为应该运行多个作业的(1 to 5000000 ).toList
等系统(默认情况下,您可以覆盖)配置为Spark
或pause
这些工作一旦他们意识到可能导致其他工作饥饿的极端GC。这可能是你的工作总是加载的主要原因。
使用reject
并使用for循环向其附加值可以大大减轻您的负担。现在,您可以并行化可变列表。
mutable List
但是,每当val mutableList = scala.collection.mutable.MutableList.empty[ Int ]
for ( i <- 1 to 5000000 ) {
mutableList.append( i )
}
val l = sc.parallelize( mutableList )
为List
时,即使这会导致多次(但严重程度不那么严重)的记忆分配(因此也会产生GC排除),这会导致half-full
整个memory relocation
1}}以前分配的内存的两倍。