【发布时间】:2015-10-01 14:54:52
【问题描述】:
受到this SO question 答案的启发,我用代码检查了一个命令式循环以防止尾递归:
let rec nothingfunc i =
match i with
| 1000000000 -> 1
| _ -> nothingfunc (i+1)
let nothingloop1 () =
let i = ref 0 in
while !i < 1000000000 do incr i done;
1
let timeit f v =
let t1 = Unix.gettimeofday() in
let _ = f v in
let t2 = Unix.gettimeofday() in
t2 -. t1
let () =
Printf.printf "recursive function: %g s\n%!" (timeit nothingfunc 0);
Printf.printf "while loop with ref counter buitin incr: %g s\n%!" (timeit nothingloop1 ());
对于字节码和本机代码,结果是
str@s131-intel:~> ./bench_loop
recursive function: 20.7656 s
while loop with ref counter buitin incr: 12.0642 s
str@s131-intel:~> ./bench_loop.opt
recursive function: 0.755594 s
while loop with ref counter buitin incr: 0.753947 s
问题是:20到12秒的执行时间相差这么大的原因是什么?
编辑,我的结论:
函数调用apply(字节码)涉及堆栈大小检查、可能的堆栈扩大和信号检查。为了获得最佳性能,本机代码编译器将提供。
(旁注:在此处询问 SO,因为它对搜索引擎友好。)
【问题讨论】:
-
opt in ocamlopt 代表优化。字节码编译器执行较少的优化,因为它从来都不是它的目的。尽管仍然进行了许多优化。例如,在当前版本的编译器 (4.03) 上,差异约为 10%(9.3 对 8.3 秒)。
标签: recursion ocaml performance-testing tail-recursion