[Haskell-cafe] Profiling nested case

Max Bolingbroke batterseapower at hotmail.com
Fri Jul 11 21:33:00 EDT 2008

> It is somehow award that passing function as an argument slow down the
> program so much. Is not Haskell a functional language and this such
> (functional) code reuse is one of its main points?

I can think of a few reasons why function passing is slow:
* There is an overhead to closure creation (I don't know how big this
is in practice, but it can be significant)
* GHC has little information about what function-typed variables mean,
because the function they are bound to is not known until runtime.
This precludes the use of inlining, rewrite rules etc, which are
absolutely key factors in making Haskell fast

Regarding your first example: currently GHC does not do loop
unrolling. It probably should though because loop unrolling reduces
braches and increases the amount of information about the execution
path that is available statically (as in e.g. the case liberation
transformation), which probably explains the increased performance you
saw by doing it manually in your first email.  Earlier this year I
implemented something somewhat similar though: fusable list literals.
In this example from your first email:

world :: SpacePoint -> VoxelColor
world point = findColor [redSphere (0,50,0) 50, greenSphere (25,-50,0)
50, blueSphere (-150,0,150) 50]
 where findColor []     = noColor
       findColor (f:fs) = case f point of
                           Just v  -> v
                           Nothing -> findColor fs

If findColor had been a function defined in terms of foldr rather than
using explicit recursion, then theres a good chance GHC 6.9 would have
fused it with the list to yield your optimized, loop unrolled,

world :: SpacePoint -> VoxelColor
world point = case redSphere (0,50,0) 50 point of
               Just v  -> v
               Nothing -> case greenSphere (25,-50,0) 50 point of
                            Just v  -> v
                            Nothing -> case blueSphere (-150,0,150) 50 point of
                                         Just v  -> v
                                         Nothing -> noColor

Incidentally, if in your most recent email castRayScene2 was your only
used of castRay, GHC would have inlined the whole definition into that
use site and you would have got castRayScene1 back again.

So, GHC does try its best to make higher order functions fast :-). But
it's quite tricky!

All the best,

More information about the Haskell-Cafe mailing list