2016-11-28 2 views
1

の驚くべき遅い私はScalaで初心者です、と私はYourKitと私のScalaコードをプロファイリングしようとしているとき、私はarray.dropの使用に関するいくつかの驚くべき知見を持っています。はmutable.array.drop

ここ

は、私が書いたものである:

私のコードの実行1分で
... 
val items = s.split(" +") // s is a string 
... 
val s1 = items.drop(2).mkString(" ") 
... 

、YourKitは、その関数呼び出しitems.drop(2)が総実行時間の約11%を取る私に言った。..

Lexer.scala:33 scala.collection.mutable.ArrayOps$ofRef.drop(int) 1054 11% 

これは本当に私には驚くべきことですが、処理を遅くする内部メモリのコピーはありますか?もしそうなら、私のシンプルなコードスニペットを最適化するベストプラクティスは何ですか?ありがとうございました。

+2

'split'は' Array'を返します。 '配列'の場合。 'drop'はコピーを作る必要があります。 –

答えて

2

これは私にとって本当に驚くべきことですが、処理が遅くなる内部メモリコピー がありますか?

ArrayOps.drop内部コールごとに新しいArrayを生成ビルダーを割り当てた、IterableLike.sliceを呼び出します。

override def slice(from: Int, until: Int): Repr = { 
    val lo = math.max(from, 0) 
    val hi = math.min(math.max(until, 0), length) 
    val elems = math.max(hi - lo, 0) 
    val b  = newBuilder 
    b.sizeHint(elems) 

    var i = lo 
    while (i < hi) { 
    b += self(i) 
    i += 1 
    } 
    b.result() 
} 

あなたが反復+割り当てのコストを見ています。これが何回起こったのか、何がコレクションのサイズなのかを指定していませんでしたが、大きければ時間がかかることがあります。

これを最適化する方法の1つは、コレクションを反復処理してheadという要素を削除する代わりにList[String]を生成することです。これは、リストを作成しArray[T]の追加トラバーサルを発生し、そのベンチマークに、これはあなたが実際には何を得る見て確認します注意:

val items = s.split(" +").toList 
val afterDrop = items.drop(2).mkString(" ") 

別の可能性は、手動でmkStringの独自のバージョンを含めるようにArray[T]を豊かにすることです

object RichOps { 
    implicit class RichArray[T](val arr: Array[T]) extends AnyVal { 
    def mkStringWithIndex(start: Int, end: Int, separator: String): String = { 
     var idx = start 
     val stringBuilder = new StringBuilder(end - start) 

     while (idx < end) { 
     stringBuilder.append(arr(idx)) 
     if (idx != end - 1) { 
      stringBuilder.append(separator) 
     } 
     idx += 1 
     } 

     stringBuilder.toString() 
    } 
    } 
} 

そして今、我々は持っている::StringBuilderを移入

object Test { 
    def main(args: Array[String]): Unit = { 
    import RichOps._ 
    val items = "hello everyone and welcome".split(" ") 
    println(items.mkStringWithIndex(2, items.length, " ")) 
    } 

収率:

and welcome 
+0

ありがとうございました!私は本当にそれを感謝します! – computereasy

+0

@computereasy歓迎します、それが助けてくれることを願っています。正しくテストするようにしてください(配列に拡張子を使用する場合)。 –