隠れパターンマッチとアロケートのコスト

http://rwmj.wordpress.com/2009/08/06/ocaml-internals-part-3-the-minor-heap/ を見ていて興味深かったコードがあったのでコピペして試してみた。

#load "unix.cma"

let f1 (a, b) = (a, b)
let f2 (x : ('a * 'b)) = x
let f3 x = x

let rec loop n f args =
  if n <= 0 then ()
  else
    let _ = f args in
    loop (n - 1) f args

let time name f =
   let start = Unix.gettimeofday () in
   f ();
   let stop = Unix.gettimeofday () in
   Printf.printf "%s: %f sec\n" name (stop -. start)

let _ =
   let loop_count = 100000000 in
   time "f1" (fun _ -> loop loop_count f1 (1, 2));
   time "f2" (fun _ -> loop loop_count f2 (1, 2));
   time "f3" (fun _ -> loop loop_count f3 (1, 2))

関数f1はパターンマッチとタプルのアロケートが発生してしまうらしいメタボなコード、関数f2は同等の型を持つがf1のような内部的な無駄な処理が発生しないもの。関数f3は何となく追加してみたもの。

実行させてみると…

:!ocaml hoge.ml
f1: 21.974001 sec
f2: 18.987098 sec
f3: 19.007618 sec

なるほど、f1の方が多少遅い。多少ね…
まぁ、性能を支配しているコードでは注意した方が良いのかもしれない。