在這種情況下,我認爲Spark驅動程序會做的事情會影響結果,而不是編譯器。 Spark是否可以優化執行流水線以避免產生冗餘重複s
。我不確定,但我認爲Spark會在內存中創建rdd1pairs
。
而是映射(String, String)
的,你可以使用(String, Unit)
:
rdd1.map(s => (s,()))
你在做什麼基本上是基於rdd1
的rdd2
過濾器。如果rdd1明顯小於rdd2,另一種方法是將rdd1
的數據表示爲廣播變量而不是RDD,並且只需過濾rdd2
即可。這樣可以避免任何混洗或縮短階段,因此可能會更快,但只有在rdd1
的數據足夠小才能適合每個節點時才能工作。
編輯:
考慮如何使用單位,而不是字符串節省空間,可以考慮下面的例子:
object size extends App {
(1 to 1000000).map(i => ("foo"+i,()))
val input = readLine("prompt> ")
}
和
object size extends App {
(1 to 1000000).map(i => ("foo"+i, "foo"+i))
val input = readLine("prompt> ")
}
在這個問題How to check heap usage of a running JVM from the command line?描述使用jstat
命令第一個版本比後者使用的堆少得多。
編輯2:
Unit
實際上是沒有內容的單獨的對象,所以從邏輯上講,它不應該要求任何序列化。類型定義包含Unit
的事實告訴你所有你需要能夠反序列化一個具有Unit類型字段的結構。
Spark默認使用Java序列化。考慮以下幾點:
object Main extends App {
import java.io.{ObjectOutputStream, FileOutputStream}
case class Foo (a: String, b:String)
case class Bar (a: String, b:String, c: Unit)
val str = "abcdef"
val foo = Foo("abcdef", "xyz")
val bar = Bar("abcdef", "xyz",())
val fos = new FileOutputStream("foo.obj")
val fo = new ObjectOutputStream(fos)
val bos = new FileOutputStream("bar.obj")
val bo = new ObjectOutputStream(bos)
fo writeObject foo
bo writeObject bar
}
這兩個文件是相同的大小:
�� sr Main$Foo3�,�z \ L at Ljava/lang/String;L bq ~ xpt abcdeft xyz
和
�� sr Main$Bar+a!N��b L at Ljava/lang/String;L bq ~ xpt abcdeft xyz
聽起來有道理,謝謝。但是,我仍然不確定與原始字符串變體相比,如何存儲對Unit的引用可以節省大量的內存。可以? – Carsten
擴展了我的答案以覆蓋該主題 – mattinbits
但在原始問題中沒有創建新的字符串。對String的引用與對'()'的引用的大小相同。 –