プログラムの一部の実行時間を推定するために単純なタイミングプロファイラーが必要でした(OCamlで書かれていますが、これは他の関数型言語にも当てはまると思います)。命令型言語で、timer.start
/などの関数を使用しますtimer.stop
。そこで、遅延評価を使用して試してみましたが、必要なものには非常にうまく機能しますが、このメソッドへの参照が見つからなかったため、アプローチに欠陥があるのか、より簡単な解決策があるのでしょうか。
ですから、問題は、関数型言語(特にOCaml)の同様の実装について知っていますか?もしそうなら、私にそれらを示してください、私は私の「貧乏人のプロファイラー」を改善するために彼らのアイデアのいくつかを借りたいです(私はこの質問を見ましたが、それは私をあまり助けませんでした)。私が見たところ、GHCにはすでにタイミング情報を収集する方法があるので、Haskellにとってはおそらく問題ではありません。
ちなみに、OCamlのマニュアル(17.4)にあるようにタイミングプロファイリングをやってみましたが、必要なものには「低レベル」すぎて、C関数レベルで多くの情報が得られ、評価が難しくなりました。正確には、OCamlコードのどの部分が原因です。
以下は、OCamlでの実装に従います(時間を測定するたびに「lazy」式を追加する必要がありますが、同時に、必要な情報量を細かく制御できます)。
open Unix (* for the timers *)
(** 'timers' associates keys (strings) to time counters,
to allow for multiple simultaneous measurements. *)
let timers : (string, (float * float)) Hashtbl.t = Hashtbl.create 1
(** starts the timer associated with key <name> *)
let timer_start (name : string) : unit =
let now = Unix.times () in
Hashtbl.replace timers name (now.tms_utime, now.tms_stime)
(** Returns time elapsed between the corresponding call to
timer_start and this call *)
let timer_stop (name : string) : float =
try
let now = Unix.times () in
let t = Hashtbl.find timers name in
(now.tms_utime -. fst t) +. (now.tms_stime -. snd t)
with
Not_found -> 0.0
(** Wrapper for the timer function using lazy evaluation *)
let time (s : string) (e : 'a Lazy.t) : 'a =
timer_start s;
let a = Lazy.force e in
let t2 = timer_stop s in
(* outputs timing information *)
Printf.printf "TIMER,%s,%f\n" s t2; a
(** Example *)
let rec fibo n =
match n with
| 0 -> 1
| 1 -> 1
| n' -> fibo (n - 1) + fibo (n - 2)
let main =
let f = time "fibo" (lazy (fibo 42)) in
Printf.printf "f = %d\n" f