(* Source code for the bytecode benchmark: one single run on a long list *) let l = Array.to_list (Array.init 1000000 (fun x -> x)) in let map' f l = (* tail recursive version of map *) let rec aux acc = function | [] -> List.rev acc | hd :: tl -> aux (f hd :: acc) tl in aux [] l in let f x = x * x in (* yes ... it overflows ... who cares? *) let test_std () = List.map f l in let test_tail_rec () = map' f l in match Sys.argv.(1) with | "1" -> test_std () | "2" -> test_tail_rec () | a -> raise (Invalid_argument a) (* Bytecode benchmark *) $ export OCAMLRUNPARAM="l=10M" $ time ./a.out 1 # non tail recursive version real 0m24.106s user 0m23.390s sys 0m0.290s $ time ./a.out 2 # tail recursive version real 0m3.627s user 0m3.390s sys 0m0.100s (* Source code for the native code benchmark: many runs on a "short" list *) let l = Array.to_list (Array.init 120000 (fun x -> x)) in let map' f l = let rec aux acc = function | [] -> List.rev acc | hd :: tl -> aux (f hd :: acc) tl in aux [] l in let f x = x * x in let test_std () = List.map f l in let test_tail_rec () = map' f l in let repeat = 100 in match Sys.argv.(1) with | "1" -> for i = 1 to repeat do test_std () done | "2" -> for i = 1 to repeat do test_tail_rec () done | a -> raise (Invalid_argument a) (* Native code benchmark *) $ time ./a.out 1 real 0m14.683s user 0m14.270s sys 0m0.190s $ time ./a.out 2 real 0m23.343s user 0m22.950s sys 0m0.070s