2017-11-28 4 views
1
val a = new Array[(Int, Int)](250000000) 
... // initialization here 

// #1 
val b = a.sortBy(_._1) 
// This part completely kills GC, 
// and I allocate plenty of heap memory (30GB) 
// more than it's trying to use 

// #2 
val b = a.sorted 
// Kills GC as efficiently as #1 

// #3 
val b = a.sortWith(_._1 < _._1) 
// This part doesn't kill GC, but 
// takes long to complete (224s) 
// and still requires 10GB of heap 

// #4 
val a = new Array[Long](250000000) 
java.util.Arrays.sort(a) 
// Alternative version 
// which takes only 2.7GB 
// and completes in 40 secs 

を発行し、私はそれが(私はGCのためのコアの#を減らすことができます知っているが、それは問題を解決していません)ソート配列:パフォーマンスがGCを殺すことによって

全16個のコアを使用して狂ったように働いている意味

さて、#3(オブジェクト、不変の操作)のオーバーヘッドがあり、5倍の時間と4倍のヒープが必要なのかどうかはわかりませんが、それは私が推測する価格です。しかし、私は#1と#2に困惑しています。私は疫病として暗黙の順序を避けるべきですか?そこには何が起こっているのですか?私はおそらくそれを間違っている?

Scalaのバージョン:2.12.4

+0

ゼロ配列をソートしていますか? –

+0

いいえ、ランダムな整数。 –

+0

プリミティブは、オブジェクトよりも速く、メモリの使用量が少なくなります。タプルオブジェクトの代わりにプリミティブなLong値を使用している場合は、すべての場合でLongを使用するか、すべてでタプルを使用する方が適切です時には1つ、時にはもう1つ。 4番目の例は、配列のコピーを作成しない唯一の例です(ソートされたコピーを作成する代わりに、配列。ソートのソートが行われます)。 – puhlen

答えて

1

これらの方法は、その後、マップされた値とその配列のコピーを作成したカスタムコンパレータで並べ替え適用することが必要です。整数値を超えたArrays.sortは、よりスマートです。数値を直接比較し、比較するメソッドを呼び出す必要はありません。

これらのメソッドの実装を見つけてください:

def sorted[B >: A](implicit ord: Ordering[B]): Repr = { 
    val len = this.length 
    val b = newBuilder 
    if (len == 1) b ++= this 
    else if (len > 1) { 
    b.sizeHint(len) 
    val arr = new Array[AnyRef](len) // Previously used ArraySeq for more compact but slower code 
    var i = 0 
    for (x <- this) { 
     arr(i) = x.asInstanceOf[AnyRef] 
     i += 1 
    } 
    java.util.Arrays.sort(arr, ord.asInstanceOf[Ordering[Object]]) 
    i = 0 
    while (i < arr.length) { 
     b += arr(i).asInstanceOf[A] 
     i += 1 
    } 
    } 
    b.result() 
} 

私はまたあなたがlong値のペアを持っているとき、あなたは基本的にペアのメモリフットプリントを持っていると思います - あなたもあれば、私は知りません各長時間のフットプリントがあります。@specialized注釈を使用して実際のロングを使用することを検討してください。http://www.scala-lang.org/api/2.12.3/scala/specialized.html

+0

'sortWith'も' sorted'を使用していますが、コンパイラなしで 'Arrays.sort'よりも遅いと言いましたが、動作します。 'sortBy'と' sorted'は単純にしません。 –

+0

#1は比較の前に配列の各要素に関数を適用する必要があります - 一度ではなく各比較に対して#2は全体のペアを比較する必要があるため、比較がより多くなります。#3は単に比較を行います –

+0

時間だけではなく、途中で作成されたゴミの数は、時間とCPUの負荷に影響します( 'sortBy'で整数の配列を作成しても説明できません)。ライブラリ関数から期待していませんでした。 –

関連する問題