buckley
buckley

Reputation: 14099

Why does this timing function always measure 0ms?

I am timing some algorithms and came up with the time function below. However, it always returns 0 ms.

The questions is why is it always 0ms when it clearly takes a few seconds. I am a beginning F# developer so I am probably missing some concepts.

Note that the question is not about a more efficient Fibonacci algorithm and I also know that the function is measuring real world time as opposed to CPU time (which can be obtained by Sys.time())

let time f x =
   let timer = new System.Diagnostics.Stopwatch()
   timer. Start ( )
   try f x finally
   printf "Took %dms" timer.ElapsedMilliseconds;;

let rec fib x = 
   if x < 2 then 1
   else fib(x-1) + fib(x-2)

time Array.iter (fun x -> ignore (fib x) ) [| 1 .. 40 |] 

Thanks for any help and pointers for a beginning F# developer

Regards, Tom

Upvotes: 5

Views: 426

Answers (2)

cfern
cfern

Reputation: 6006

The problem is that your time function expects a one-argument function, but you're calling it with a two-argument one:

time Array.iter (fun x -> ...) [|1..40|]
                 ^- first arg   ^- second arg

To get the result you want, use parentheses

time (Array.iter (fun x -> ignore (fib x) )) [| 1 .. 40 |] 
      ^- a single partially curried function  ^- a single argument

For example in FSI:

> time ( Array.iter (fun x -> ignore (fib x) ) ) [| 1 .. 40 |];;
Took 6589msval it : unit = ()

Better yet, if you're testing in F# interactive, use the #time directive and FSI will do the timing for you. Example:

> #time;;

--> Timing now on

> Array.iter (fun x -> ignore (fib x) ) [| 1 .. 40 |];;
Real: 00:00:06.816, CPU: 00:00:06.218, GC gen0: 0, gen1: 0, gen2: 0
val it : unit = ()

Upvotes: 6

kvb
kvb

Reputation: 55195

Your problem is that because of how function application works, you're doing this:

((time Array.iter) (fun x -> ignore (fib x))) [| 1 .. 40 |]

so you're timing how long it takes to apply Array.iter to the function value fun x -> ignore (fib x), which doesn't take very long at all, and results in another function of type int array -> (), which you're then applying to [| 1 .. 40 |]. Instead, you ought to try

time (Array.iter (fun x -> ignore (fib x))) [| 1 .. 40 |] 

Upvotes: 5

Related Questions