I’m surprised how much slower the List range is for the example below. On my machine the for loop is a factor of 8 or so quicker.
Is an actual list of 10,000,000 elements created first? And if so, is there a reason (other than it has not been done yet) why this can’t be optimised away by the compiler?
open System
open System.Diagnostics
let timeFunction f v =
let sw = Stopwatch.StartNew()
let result = f v
sw.ElapsedMilliseconds
let length = 10000000
let doSomething n =
(float n) ** 0.1 |> ignore
let listIter n =
[1..length] |> List.iter (fun x -> doSomething (x+n))
let forLoop n =
for x = 1 to length do
doSomething (x+n)
printf "listIter : %d\n" (timeFunction listIter 1) // c50
GC.Collect()
printf "forLoop : %d\n" (timeFunction forLoop 1) // c1000
GC.Collect()
Using ILSpy,
listIterlooks like this:Here are the basic steps involved:
RangeInt32creates anIEnumerable(which is inexplicably wrapped byCreateSequence)SeqModule.ToListbuilds a list from that sequencelistIter@17(your lambda) is new’d upListModule.Iteratetraverses the list calling the lambda for each elementvs
forLoop, which doesn’t look much different from what you’ve written:…no
IEnumerable, lambda (it’s automatically inlined), or list creation. There’s a potentially significant difference in the amount of work being done.EDIT
For curiosity’s sake, here are FSI timings for
list,seq, andforloop versions:and the
seqversion for reference: