【发布时间】:2022-02-04 05:48:29
【问题描述】:
最近,我想优化我的 OCaml 程序。有人建议我做一个perf 分析。
好吧,当我看到Sys.time() 是在我的程序中花费最多时间的函数时,我感到很惊讶,因为我在每个循环中都调用它。
我会尽量少调用它,但我想知道,是否存在一种更有效的方法来强制程序在一定时间后返回?
也许比Sys.time 更有效地获取当前处理时间,或者完全不同的东西。
【问题讨论】:
最近,我想优化我的 OCaml 程序。有人建议我做一个perf 分析。
好吧,当我看到Sys.time() 是在我的程序中花费最多时间的函数时,我感到很惊讶,因为我在每个循环中都调用它。
我会尽量少调用它,但我想知道,是否存在一种更有效的方法来强制程序在一定时间后返回?
也许比Sys.time 更有效地获取当前处理时间,或者完全不同的东西。
【问题讨论】:
您可以按照 Jeffrey 的建议使用更高效的 Unix.gettimeofday 函数,但除此之外,您还可以尝试减少比较。
首先,您可以仅每千次(或更多,或更少,选择正确的数字)迭代检查一次,例如,
if i mod 10000 = 0 && check_timeout ()
then do_work ()
else raise Timeout
或者,如果您的代码已分配并且您并没有真正为超时的确切时间而烦恼(即,您可以等待比选定的超时时间长一点,但希望至少在指定的时间内运行您的函数),然后您可以设置闹钟。每个主要集合都会检查它,如果您的代码没有分配很多1),它可能需要一些时间才能触发,例如,
exception Timeout
let rec infinite () =
let x = Random.int64 0xDEADBEEFL in
Format.printf "%Ld\n" x;
infinite ()
let max_time = 60.
let () =
let start = Sys.time () in
let alarm = Gc.create_alarm (fun () ->
if Sys.time () -. start > max_time
then raise Timeout) in
let () = try infinite () with Timeout -> () in
Gc.delete_alarm alarm
另一个适用于 Unix 系统并且仍然需要在循环内分配的选项是依赖 Unix 警报信号。这是性能最高的选项,但它存在一些问题,例如便携性和可靠性(如果其他人决定使用警报信号,它将无法工作)。
let timeout = ref false
let rec infinite () =
if not timeout.contents then infinite ()
let () =
let stopit = Sys.Signal_handle (fun _ -> timeout := true) in
Sys.set_signal Sys.sigalrm stopit;
ignore (Unix.alarm 10);
infinite ();
1) 这个例子没有分配太多,它可以很好地处理几十秒的超时。如果超时时间小于 10 秒,则它会运行超过指定的持续时间,因为通常需要几秒钟才能启动第一个主要收集。
【讨论】:
您似乎在 Windows 系统上运行。我无法访问 Windows,但在我的 Mac 上,Unix.gettimeofday 比 Sys.time 快得多。它返回挂钟时间而不是处理时间,但实际上我通常想要挂钟时间。我很少对代码上花费的具体 CPU 周期数感兴趣。
这是我在 Mac 上运行的测试程序:
let start_time = Unix.gettimeofday () in
for i = 1 to 10000000 do
ignore (Sys.time ())
done;
let end_time = Unix.gettimeofday () in
Printf.printf "Sys.time %f\n" (end_time -. start_time);
let start_time = Unix.gettimeofday () in
for i = 1 to 10000000 do
ignore (Unix.gettimeofday ())
done;
let end_time = Unix.gettimeofday () in
Printf.printf "Unix.gettimeofday %f\n" (end_time -. start_time)
输出:
$ ./m
Sys.time 4.060067
Unix.gettimeofday 0.320934
在 Linux 环境下,也有类似的结果(@Butanium 供稿):
Sys.time 4.097320
Unix.gettimeofday 0.508475
这是我从 Ubuntu 18.04.4 得到的结果
Sys.time 6.156210
Unix.gettimeofday 0.309533
(这是一个装饰有骷髅图片的小型 NUC 系统。)
总结就是不同系统的时间不同,但是gettimeofday快很多。
【讨论】:
Unix.gettimeofday