Spark中的iterable和Array之间的关系

时间:2016-12-21 14:01:07

标签: arrays scala apache-spark

我注意到如果我在RDD上应用mapPartitions,分区将获得一个可迭代对象。在mapPartitions函数中,然后我调用iterable的toArray成员函数将该可迭代对象转换为Array对象。调用toArray是否涉及复制,还是只是开始引用与数组相同的内存部分?如果涉及复制,有什么方法可以防止复制?

1 个答案:

答案 0 :(得分:3)

对您的问题进行了一次重要更正 - mapPartitions期间公开的分区数据结构是迭代器,而不是Iterable。这是界面差异:

  • Iterator具有next()hasNext()方法,可让您访问集合中的每个元素一次。一旦调用迭代器的next()方法,最后一个元素就消失了(除非你把它存储在变量中)。
  • Iterable可以随时生成Iterator。这使您可以根据需要多次访问每个元素。

在实施方面,Iterator可以流式传输数据。你真的只需要一次在内存中有一个元素,在调用next()时加载。如果您正在使用Spark(sc.textFile)读取文本文件,那么它就是这样做的,并且几乎不使用任何内存来进行简单的迭代迭代。

您绝对可以致电iterator.toArray,但您可能不想这样做。你最终将所有数据推入内存(Spark一次只能加载一个元素,因为你一次要求所有这些元素),并复制每一段数据(对于基元,如{ {1}})或为每个数据分配一个新的引用(对于Int,如AnyRef)。没有办法阻止这种复制。

有时将分区迭代器转换为数组是您想要做的事情,但这些用例很少见。由于不必要的分配和GC,您可能会因内存不足而导致应用程序运行速度变慢,因此请仔细考虑是否真的需要它!