Profiling OCaml with gprof and jbuilder
I am currently using OCaml for part of my research and ran into more trouble than expected when trying to profile my program. This post details step by step how to compile an OCaml program using dune(jbuilder) to profile the binary using gprof.
As an example program to profile, I will use a short code implementing the tak function of dear prof. Takeuchi.
(* tak.ml *)
let rec tak x y z =
if x <= y then y
else
tak (tak (x-1) y z)
(tak (y-1) z x)
(tak (z-1) x y)
let () = print_endline (string_of_int (tak 18 12 6))
First, we will compile with the -p
option of ocamlopt
to turn on profiling
and run the program.
ocamlopt -p tak.ml -o tak
./tak
This should hopefully output 18
and create a file called gmon.out
.
The next step is, as usual with gprof
, to generate the profile from gmon.out
gprof tak gmon.out > profile.txt
If the profile looks good, then you can skip the next step. If, as on my
computer, you get an empty profile, then you probably have a buggy version of
gcc. A workaround seems to be to disable position independent code with the
-no-pie
option, although I am not sure exactly why. The compile command then
becomes
ocamlopt -p tak.ml -o tak -ccopt -no-pie
and by re-running the program and gprof
, profile.txt
should now actually
contain the program profile.
The last step is to get this working with jbuilder
by telling it to pass
the above options to ocamlopt
. This can be done with the ocamlopt_flags
,
and the jbuild
file can therefore be defined as follow.
(jbuild_version 1)
(executable (
(name tak)
(ocamlopt_flags (:standard -p -ccopt -no-pie))
))
Note that you can remove the -ccopt -no-pie
part if you did not need it when
compiling with ocamlopt
directly. We can now compile our program with
jbuilder
.
rm tak tak.cm* tak.o gmon.out profile.txt # cleanup first
jbuilder build tak.exe
and we should be able to generate a profile.
./_build/default/tak.exe
gprof _build/default/tak.exe gmon.out > profile.txt
Although I did not try it, it seems that it should be possible to
change the flags used by jbuilder
using command line arguments, so it
could also be worth trying in combination with the steps described above.