2012-10-16 1 views
5

私は大規模な構造を介して再帰的に小さな文字列(例:短い文字列または単純なケースクラス)を持つセットとマップを取ることを含むコードを書いています。少数の)オブジェクトをセットまたはマップに追加します。変更可能なセットとマップを使用すると、不変のものよりも大幅なスピードアップが得られるように見えますが、その違いを定量的に評価することができません。Scalaでは、ガベージコレクションに関して、不変で変更可能なセットとマップがどのように比較されますか?

不変なデータ構造を使用しているときにScalaのガーベッジコレクションが大幅に遅くなることは意味がありますか?変更可能なデータ構造を使用するとこれが解決されますか?

答えて

5

Scalaの不変なコレクションは驚くほど効率的です。主に、構造が変更されると、構造の多くが再利用されるためです。

しかし、変更をたくさん行うと、変更可能な構造がより適している可能性があります。実際にはScala Collection APIは内部的に多くの場所で何をしていますか?新しいものを構築するためには可変データ構造を使用し、最後の手順としては不変のものを作成して返します。

-1

Scala変更可能なデータ構造は、メモリを事前に割り当てることによって、変更可能なデータ構造よりも効率が向上します。彼らはより多くの挿入に適しています(なぜ彼らは変更可能です)。関数の実装を見てみましょう+ =地図が延びデフォルト変更可能なコレクション、HashMapの、中:

https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/mutable/HashMap.scala#L84

def += (kv: (A, B)): this.type = { 
    val e = findEntry(kv._1) 
    if (e == null) addEntry(new Entry(kv._1, kv._2)) 
    else e.value = kv._2 
    this 
} 

HashMapのは、ハッシュテーブルを使用して変更可能な地図を実装し、

addEntryを定義します

https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/mutable/HashTable.scala#L117

protected def addEntry(e: Entry) { 
    val h = index(elemHashCode(e.key)) 
    e.next = table(h).asInstanceOf[Entry] 
    table(h) = e 
    tableSize = tableSize + 1 
    nnSizeMapAdd(h) 
    if (tableSize > threshold) 
    resize(2 * table.length) 
} 

コレクションのサイズがしきい値に達するたびに倍増しています。したがって、空の変更可能なデータ構造に一度に1つのエントリだけを繰り返し追加する場合は、log(n)回のサイズを変更する必要があります。私は、不変のデータ構造の実装を深く見ていませんでしたが、私はすべてのインサートにサイズを変更する必要があると仮定しています。したがって、あなたのパフォーマンスの格差。

関連する問題