[Haskell-cafe] Profiling nested case

Mitar mmitar at gmail.com
Wed Jul 9 23:08:06 EDT 2008


Hi!

I am making a simple raycasting engine and have a function which take
a point in space and return a color of an object (if there is any) at
this point in space.

And because the whole thing is really slow (or was really slow) on
simple examples I decided to profile it. It takes around 60 seconds
for a 640x480 px image with 400 depth of field. This is at worst
122,880,000 calculations (if the scene is rather empty) of a
coordinate of a point in space and then checking for a color. And 60
seconds look really a lot to me for that.

So I went profiling and found out that the strange part of code is the
main color checking function which has a list of objects (at this time
the list is hardcoded). It looks like this:

world :: SpacePoint -> VoxelColor
world point = case msum . sequence elements $ point of
                Just v  -> v
                Nothing -> noColor
  where elements = [redSphere (0,50,0) 50, greenSphere (25,-50,0) 50,
blueSphere (-150,0,150) 50]

So three spheres in a world and I check if the point is in any of
them. Like that:

sphere :: SpacePoint -> BasicReal -> VoxelColor -> WorldElement --
center of sphere, it's radius, it's color
sphere (x0,y0,z0) r color (x,y,z)
  | x' * x' + y' * y' + z' * z' <= r * r = Just color
  | otherwise                            = Nothing
    where x' = x - x0
          y' = y - y0
          z' = z - z0

redSphere :: SpacePoint -> BasicReal -> WorldElement
redSphere c r = sphere c r redColor

So profiling told me that world function takes 38.4 % of all running
time. So I decided to play with it. Maybe a more direct approach would
be better:

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

Great, it improved. To 40 s. But still it was too much. I tried this:

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

And it took 15 s. And also the profiling was like I would anticipate.
Calculating points coordinates and checking spheres takes almost all
time.

So any suggestions how could I build a list of objects to check at
runtime and still have this third performance? Why this big
difference?

(I am using GHC 6.8.3 with -O2 compile switch.)

(The <* operator is casting a ray, that is multiplying a ray direction
vector with a scalar factor.)


Mitar
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Main-case.prof
Type: application/octet-stream
Size: 6535 bytes
Desc: not available
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20080710/7a21c7c1/Main-case.obj
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Main-rec.prof
Type: application/octet-stream
Size: 6536 bytes
Desc: not available
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20080710/7a21c7c1/Main-rec.obj
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Main-seq.prof
Type: application/octet-stream
Size: 6414 bytes
Desc: not available
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20080710/7a21c7c1/Main-seq.obj


More information about the Haskell-Cafe mailing list