This blog has moved on http://blog.khigia.net/blog.html and this post is at http://blog.khigia.net/wp-import/fsharp/2008/03/30/ocaml-vs-f-for-big-integer-surprising-performance-test.html
Was inspired by Rober Pickering post about a post about Euler problem 14 …
Without changing the algorithm, I ran a simple test to compare F#, ocaml byte code and ocaml native code … and the result is quite surprising, for me at least!
The program do a lot of computation on integer (even 64 bits); I remember (no ref) that ocaml is more efficient for floating point operation that for integer. But anyway, just wanted an idea of how to port this code to Ocaml.
Following is the code in F# as seen on cited post:
#light
let rec seq_length x n =
match x with
| x when x = 0L -> (n + 1)
| x when x = 1L -> seq_length 0L (n + 1)
| x when x%2L=0L ->seq_length (x/2L) (n + 1)
| _ -> seq_length (3L*x + 1L) (n + 1)
let rec loop i imax n =
let n’ = seq_length i 0
let imax, n = if n’ > n then i, n’ else imax, n
if i < 1000000L then loop (i + 1L) imax n else imax
print_any (loop 1L 0L 0)[/sourcecode]
And here is an Ocaml version:
[sourcecode language="csharp"]
let ( ** ) = Int64.mul
let ( // ) = Int64.div
let ( %% ) = Int64.rem
let rec seq_length x n =
match x with
| 0L -> (n + 1)
| 1L -> seq_length 0L (n + 1)
| x when x %% 2L = 0L -> seq_length (x // 2L) (n + 1)
| _ -> seq_length (Int64.succ (3L ** x)) (n + 1)
let rec loop i imax n =
let n’ = seq_length i 0 in
let imax, n = if n’ > n then (i, n’) else (imax, n) in
if i < 1000000L then loop (Int64.succ i) imax n else imax
let _ = print_string (Int64.to_string (loop 1L 0L 0))[/sourcecode]
Surprisingly (for me!), the compiled F# code is much faster:
- time mono eul14.exe: 12.979s
- time ./eul14.byte: 58.145s
- time ./eul14.native: 30.234s
I’m not sure why Ocaml seems to be slower for this test. Can it be a GC issue?