2012-06-03 17 views
10

consideran este código en C#:¿Por qué Seq.iter y Seq.map son mucho más lentos?

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!!!! 

¿Por qué el iter y map funciones en el módulo Seq mucho más lento que los equivalentes Array y List módulo?

Respuesta

13

Una vez que llame al Seq, perderá la información del tipo - pasar al siguiente elemento de la lista requiere una llamada al IEnumerator.MoveNext. Comparar con Array que acaba de incrementar un índice y para List puede desreferenciar un puntero. Básicamente, recibirá una llamada de función adicional para cada elemento de la lista.

Las conversiones de nuevo a List y Array también ralentizar el código abajo por razones similares

+0

que tiene sentido, gracias por señalarlo – theburningmonk

+0

Aunque probablemente tiene usted razón sobre la causa real. Realmente no responde la pregunta en un nivel más profundo. ¿Por qué eligieron usar MoveNext? Como se hizo a través de la biblioteca de linq, podría comenzar con una verificación de tipo y, en el caso de una lista o una matriz, elegir la versión correspondiente, entonces la diferencia para las secuencias grandes sería negligente. –

Cuestiones relacionadas