Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this timing function always measure 0ms?

Tags:

f#

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

like image 782
buckley Avatar asked Jan 28 '11 13:01

buckley


2 Answers

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 = ()
like image 177
cfern Avatar answered Oct 06 '22 22:10

cfern


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 |] 
like image 43
kvb Avatar answered Oct 06 '22 21:10

kvb