2015-09-04 51 views
6

使用Scala和火花,我有以下結構:Scala編譯器如何處理未使用的變量值?

val rdd1: RDD[String] = ... 
val rdd2: RDD[(String, Any)] = ... 

val rdd1pairs = rdd1.map(s => (s, s)) 
val result = rdd2.join(rdd1pairs) 
       .map { case (_: String, (e: Any, _)) => e } 

映射rdd1的目的成PairRDD是在隨後的步驟與rdd2加入。但是,我實際上只對rdd2的值感興趣,因此最後一行中的映射步驟省略了密鑰。實際上,出於效率原因,這是用Spark的join()執行的rdd2rdd1之間的交點。

我的問題涉及到rdd1pairs的鍵:它們僅在第一個映射步驟中爲語法原因(允許連接)創建,後來被丟棄而沒有任何用法。編譯器如何處理這個問題?無論我使用字符串s(如示例中所示),是否在內存消耗方面都很重要?我應該用null還是0替換它以節省一點存儲空間?編譯器是否實際創建和存儲這些對象(引用),還是會注意到它們從未被使用過?

回答

3

在這種情況下,我認爲Spark驅動程序會做的事情會影響結果,而不是編譯器。 Spark是否可以優化執行流水線以避免產生冗餘重複s。我不確定,但我認爲Spark會在內存中創建rdd1pairs

而是映射(String, String)的,你可以使用(String, Unit)

rdd1.map(s => (s,())) 

你在做什麼基本上是基於rdd1rdd2過濾器。如果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 
+0

聽起來有道理,謝謝。但是,我仍然不確定與原始字符串變體相比,如何存儲對Unit的引用可以節省大量的內存。可以? – Carsten

+0

擴展了我的答案以覆蓋該主題 – mattinbits

+1

但在原始問題中沒有創建新的字符串。對String的引用與對'()'的引用的大小相同。 –

相關問題