Time a function: Difference between revisions

From Rosetta Code
Content added Content deleted
(add Common Lisp example)
(added ocaml)
Line 44: Line 44:


=={{header|C++}}==
=={{header|C++}}==
#include <ctime>
<cpp>#include <ctime>
#include <iostream>
#include <iostream>
using namespace std;
using namespace std;

int identity(int x) { return x; }
int identity(int x) { return x; }
int sum(int num) {
int sum(int num) {
for (int i = 0; i < 1000000; i++)
for (int i = 0; i < 1000000; i++)
num += i;
num += i;
return num;
return num;
}
}

double time_it(int (*action)(int), int arg) {
double time_it(int (*action)(int), int arg) {
clock_t start_time = clock();
clock_t start_time = clock();
action(arg);
action(arg);
clock_t finis_time = clock();
clock_t finis_time = clock();
return ((double) (finis_time - start_time)) / CLOCKS_PER_SEC;
return ((double) (finis_time - start_time)) / CLOCKS_PER_SEC;
}
}

int main() {
int main() {
cout << "Identity(4) takes " << time_it(identity, 4) << " seconds." << endl;
cout << "Identity(4) takes " << time_it(identity, 4) << " seconds." << endl;
cout << "Sum(4) takes " << time_it(sum, 4) << " seconds." << endl;
cout << "Sum(4) takes " << time_it(sum, 4) << " seconds." << endl;
return 0;
return 0;
}</cpp>
}


===Example===
===Example===
Line 108: Line 108:
(6!:2,7!:2) '|: 50 50 50 $ i. 50^3'
(6!:2,7!:2) '|: 50 50 50 $ i. 50^3'
0.00387912 1.57414e6
0.00387912 1.57414e6

=={{header|OCaml}}==
<ocaml>let time_it action arg =
let start_time = Sys.time () in
ignore (action arg);
let finish_time = Sys.time () in
finish_time -. start_time</ocaml>

===Example===
# Printf.printf "Identity(4) takes %f seconds.\n" (time_it (fun x -> x) 4);;
Identity(4) takes 0.000000 seconds.
- : unit = ()
# let sum x = let num = ref x in for i = 0 to 999999 do num := !num + i done; !num;;
val sum : int -> int = <fun>
# Printf.printf "Sum(4) takes %f seconds.\n" (time_it sum 4);;
Sum(4) takes 0.084005 seconds.
- : unit = ()


=={{header|Python}}==
=={{header|Python}}==
Line 113: Line 130:


'''Note:''' There is an overhead in executing a function that does nothing.
'''Note:''' There is an overhead in executing a function that does nothing.
import sys, timeit
<python>import sys, timeit
def usec(function, arguments):
def usec(function, arguments):
modname, funcname = __name__, function.__name__
modname, funcname = __name__, function.__name__
timer = timeit.Timer(stmt='%(funcname)s(*args)' % vars(),
timer = timeit.Timer(stmt='%(funcname)s(*args)' % vars(),
setup='from %(modname)s import %(funcname)s; args=%(arguments)r' % vars())
setup='from %(modname)s import %(funcname)s; args=%(arguments)r' % vars())
try:
try:
t, N = 0, 1
t, N = 0, 1
while t < 0.2:
while t < 0.2:
t = min(timer.repeat(repeat=3, number=N))
t = min(timer.repeat(repeat=3, number=N))
N *= 10
N *= 10
microseconds = round(10000000 * t / N, 1) # per loop
microseconds = round(10000000 * t / N, 1) # per loop
return microseconds
return microseconds
except:
except:
timer.print_exc(file=sys.stderr)
timer.print_exc(file=sys.stderr)
raise
raise


def nothing(): pass
def nothing(): pass
def identity(x): return x
def identity(x): return x</python>

===Example===
===Example===
>>> print usec(nothing, [])
>>> print usec(nothing, [])

Revision as of 19:30, 18 August 2008

Task
Time a function
You are encouraged to solve this task according to the task description, using any language you may know.

What time does it take to execute a `function' with a given `arguments'.

Use a timer with the least granularity available on your system.

What caveats are there?

This task is intended as a subtask for Measure relative performance of sorting algorithms implementations.

Ada

with Ada.Calendar; use Ada.Calendar;
with Ada.Text_Io; use Ada.Text_Io;

procedure Query_Performance is
   type Proc_Access is access procedure(X : in out Integer);
   function Time_It(Action : Proc_Access; Arg : Integer) return Duration is
      Start_Time : Time := Clock;
      Finis_Time : Time;
      Func_Arg : Integer := Arg;
   begin
      Action(Func_Arg);
      Finis_Time := Clock;
      return Finis_Time - Start_Time;
   end Time_It;
   procedure Identity(X : in out Integer) is
   begin
      X := X;
   end Identity;
   procedure Sum (Num : in out Integer) is
   begin
      for I in 1..1000 loop
         Num := Num + I;
      end loop;
   end Sum;
   Id_Access : Proc_Access := Identity'access;
   Sum_Access : Proc_Access := Sum'access;
   
begin
   Put_Line("Identity(4) takes" & Duration'Image(Time_It(Id_Access, 4)) & " seconds.");
   Put_Line("Sum(4) takes:" & Duration'Image(Time_It(Sum_Access, 4)) & " seconds.");
end Query_Performance;

Example

Identity(4) takes 0.000001117 seconds.
Sum(4) takes: 0.000003632 seconds.

C++

<cpp>#include <ctime>

  1. include <iostream>

using namespace std;

int identity(int x) { return x; } int sum(int num) {

 for (int i = 0; i < 1000000; i++)
   num += i;
 return num;

}

double time_it(int (*action)(int), int arg) {

 clock_t start_time = clock();
 action(arg);
 clock_t finis_time = clock();
 return ((double) (finis_time - start_time)) / CLOCKS_PER_SEC;

}

int main() {

 cout << "Identity(4) takes " << time_it(identity, 4) << " seconds." << endl;
 cout << "Sum(4) takes " << time_it(sum, 4) << " seconds." << endl;
 return 0;

}</cpp>

Example

Identity(4) takes 0 seconds.
Sum(4) takes 0.01 seconds.

Common Lisp

Common Lisp provides a standard utility for performance measurement, time:

CL-USER> (time (reduce #'+ (make-list 100000 :initial-element 1)))
Evaluation took:
  0.151 seconds of real time
  0.019035 seconds of user run time
  0.01807 seconds of system run time
  0 calls to %EVAL
  0 page faults and
  2,400,256 bytes consed.

(The example output here is from SBCL.)

However, it merely prints textual information to trace output, so the information is not readily available for further processing (except by parsing it in a CL-implementation-specific manner).

The functions get-internal-run-time and get-internal-real-time may be used to get time information programmatically, with at least one-second granularity (and usually more). Here is a function which uses them to measure the time taken for one execution of a provided function:

(defun timings (function)
  (let ((real-base (get-internal-real-time))
        (run-base (get-internal-run-time)))
    (funcall function)
    (values (/ (- (get-internal-real-time) real-base) internal-time-units-per-second)
            (/ (- (get-internal-run-time) run-base) internal-time-units-per-second))))
CL-USER> (timings (lambda () (reduce #'+ (make-list 100000 :initial-element 1))))
17/500
7/250

J

Time and space requirements are tested using verbs obtained through the Foreign conjunction (!:). 6!:2 returns time required for execution, in floating-point measurement of seconds. 7!:2 returns a measurement of space required to execute. Both receive as input a sentence for execution.
When the Memoize feature or similar techniques are used, execution time and space can both be affected by prior calculations.

Example

   (6!:2,7!:2) '|: 50 50 50 $ i. 50^3'
0.00387912 1.57414e6

OCaml

<ocaml>let time_it action arg =

 let start_time = Sys.time () in
 ignore (action arg);
 let finish_time = Sys.time () in
 finish_time -. start_time</ocaml>

Example

# Printf.printf "Identity(4) takes %f seconds.\n" (time_it (fun x -> x) 4);;
Identity(4) takes 0.000000 seconds.
- : unit = ()
# let sum x = let num = ref x in for i = 0 to 999999 do num := !num + i done; !num;;
val sum : int -> int = <fun>
# Printf.printf "Sum(4) takes %f seconds.\n" (time_it sum 4);;
Sum(4) takes 0.084005 seconds.
- : unit = ()

Python

Given function and arguments return a time (in microseconds) it takes to make the call.

Note: There is an overhead in executing a function that does nothing. <python>import sys, timeit def usec(function, arguments):

   modname, funcname = __name__, function.__name__
   timer = timeit.Timer(stmt='%(funcname)s(*args)' % vars(),
                        setup='from %(modname)s import %(funcname)s; args=%(arguments)r' % vars())
   try:
       t, N = 0, 1
       while t < 0.2:            
           t = min(timer.repeat(repeat=3, number=N))            
           N *= 10
       microseconds = round(10000000 * t / N, 1) # per loop
       return microseconds 
   except:
       timer.print_exc(file=sys.stderr)
       raise
def nothing(): pass
def identity(x): return x</python>

Example

>>> print usec(nothing, [])
1.7
>>> print usec(identity, [1])
2.2
>>> print usec(pow, (2, 100))
3.3
>>> print map(lambda n: str(usec(qsort, (range(n),))), range(10))
['2.7', '2.8', '31.4', '38.1', '58.0', '76.2', '100.5', '130.0', '149.3', '180.0']

where qsort() implemented on Quicksort page. Timings show that the implementation of qsort() has quadratic dependence on sequence length N for already sorted sequences (instead of O(N*log(N)) in average).