1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
(* Tries to show the profile cost of composing small functions. *)
(* Small functions: permutations of [0 .. n-1] *)
let n = 100000
let rotate r = fun k -> (k + r) mod n
let reverse i j = fun k -> if i <= k && k <= j then j + i - k else k
let splice l i j = fun k ->
if k < j then if k < i then k else k + l + 1
else if k <= j + l then k - j + i
else let k' = k - l - 1 in if k' < i then k' else k
open Benchmark
open Printf
let ncomp = 400 (* Number of compositions *)
let make_perms =
(* Create a random list of transformations *)
Random.self_init();
let rec random_perm ((p_f, p_v) as acc) i =
if i <= 0 then acc else
let c = Random.int 3 in
(* New function *)
let p =
if c = 0 then rotate (Random.int n)
else if c = 1 then reverse (Random.int n) (Random.int n)
else (* c = 2 *) splice (Random.int n) (Random.int n) (Random.int n) in
(* Corresponding array transformer *)
let p_vec w v =
for i = 0 to Array.length v - 1 do w.(i) <- p v.(i) done in
random_perm (p :: p_f, p_vec :: p_v) (i - 1) in
random_perm ([], [])
let () =
let ncomp = 300 in
let p_f, p_v = make_perms ncomp in
let v = Array.init n (fun k -> k) in
let do_f () =
let f = List.fold_left (fun f f0 -> (fun k -> f0(f k))) (fun k -> k) p_f in
Array.map f v
and do_v () =
snd(List.fold_left (fun (w,v) f -> f w v; (v,w)) (Array.make n 0, v) p_v)
in
let res = throughputN ~repeat:3 5 [("fun", do_f, ());
("vec", do_v, ()) ] in
tabulate res
|