Optimization
Compiling your Program for Profiling
The GHC compiler has mature support for compiling with profiling annotations.
Using the -prof
and -fprof-auto
flags when compiling will add support to your binary for profiling flags for use at runtime.
Suppose we have this program:
main = print (fib 30)
fib n = if n < 2 then 1 else fib (n-1) + fib (n-2)
Compiled it like so:
ghc -prof -fprof-auto -rtsopts Main.hs
Then ran it with runtime system options for profiling:
./Main +RTS -p
We will see a main.prof
file created post execution (once the program has exited), and this will give us all sorts of profiling information such as cost centers which gives us a breakdown of the cost associated with running the various parts of the code:
Wed Oct 12 16:14 2011 Time and Allocation Profiling Report (Final)
Main +RTS -p -RTS
total time = 0.68 secs (34 ticks @ 20 ms)
total alloc = 204,677,844 bytes (excludes profiling overheads)
COST CENTRE MODULE %time %alloc
fib Main 100.0 100.0
individual inherited
COST CENTRE MODULE no. entries %time %alloc %time %alloc
MAIN MAIN 102 0 0.0 0.0 100.0 100.0
CAF GHC.IO.Handle.FD 128 0 0.0 0.0 0.0 0.0
CAF GHC.IO.Encoding.Iconv 120 0 0.0 0.0 0.0 0.0
CAF GHC.Conc.Signal 110 0 0.0 0.0 0.0 0.0
CAF Main 108 0 0.0 0.0 100.0 100.0
main Main 204 1 0.0 0.0 100.0 100.0
fib Main 205 2692537 100.0 100.0 100.0 100.0
Cost Centers
Cost centers are annotations on a Haskell program which can be added automatically by the GHC compiler — using -fprot-auto
— or by a programmer using {-# SCC "name" #-} <expression>
, where “name” is any name you wish and <expression>
is any valid Haskell expression:
-- Main.hs
main :: IO ()
main = do let l = [1..9999999]
print $ {-# SCC "print_list" #-} (length l)
Compiling with -fprof
and running with +RTS -p
e.g. ghc -prof -rtsopts Main.hs && ./Main.hs +RTS -p
would produce Main.prof
once the program’s exited.