2012-06-03 11 views
10

は、F#でこのコードを考えてみましょう:Seq.iterとSeq.mapはなぜそれほど遅くなっていますか?

let n = 10000000 
let arr = Array.init n (fun _ -> 0) 

let rec buildList n acc i = if i = n then acc else buildList n (0::acc) (i + 1) 
let lst = buildList n [] 0 

let doNothing _ =() 
let incr x = x + 1 

#time 

arr |> Array.iter doNothing   // this takes 14ms 
arr |> Seq.iter doNothing   // this takes 74ms 

lst |> List.iter doNothing   // this takes 19ms 
lst |> Seq.iter doNothing   // this takes 88ms 

arr |> Array.map incr    // this takes 33ms 
arr |> Seq.map incr |> Seq.toArray // this takes 231ms! 

lst |> List.map incr    // this takes 753ms 
lst |> Seq.map incr |> Seq.toList // this takes 2111ms!!!! 

なぜSeqモジュール上のitermap機能がArrayListモジュール同等物よりもそんなに遅いですか?

答えて

13

Seqに電話をかけたら、タイプ情報が失われます。リストの次の要素に移動するには、IEnumerator.MoveNextを呼び出す必要があります。 Arrayの場合はインデックスを増やし、Listの場合はポインタを逆参照できます。基本的には、リスト内の各要素に対して特別な関数呼び出しが行われています。

変換バックListArrayにも理にかなっている同様の理由

+0

、あなたはおそらく、実際の原因について正しいですけれども – theburningmonk

+0

をそのを指摘してくれてありがとうのためにダウンしたコードを遅らせます。それは本当に深いレベルの質問には答えません。なぜ彼らはMoveNextの使用を選択しましたか? linqライブラリを使って行ったように、タイプチェックで始めることができます。リストや配列の場合は、一致するバージョンを選択してから大きなシーケンスの違いを無視できます –

関連する問題