[Haskell-cafe] 3GB allocation, 75% CPU usage from a callback function

Daniel Fischer daniel.is.fischer at googlemail.com
Sat Jan 29 18:01:25 CET 2011


On Saturday 29 January 2011 17:29:02, Edward Amsden wrote:
> (Note that the function produced by newSinWave is the one actually
> registered as a callback:
>
> newSinWave :: Int -> Float -> IO (CFloat -> IO CFloat)
> newSinWave sampleRate freq =
>  do ioref <- newIORef (0::Integer)
>     let multiplier = 2 * pi * freq /
>                      (fromIntegral sampleRate)
>
>     return (\_ -> {-# SCC "sinWave" #-}
>              do t <- readIORef ioref
>                 modifyIORef ioref (+1)
>                 return $ fromRational $
>                   toRational $

fromRational . toRational is a big no-no here. It will still be slow when 
the new implementation makes it into base, but currently it's 
slooooooooooooow.
If you replace it with realToFrac and compile with optimisations, it should 
be rewritten to a no-op.

>                   sin (fromIntegral t *
>                        multiplier))
>
> I profiled this since when my program registered with the jack server
> and started taking callbacks, it was using about 75% cpu
> (in contrast, the echo program included with the jack package uses
> less than 2%). The following two lines are of concern to me:
>
> "total alloc = 3,040,397,164 bytes  (excludes profiling overheads)"
> My program uses 3GB of virtual memory over a 15 second run?

Sequentially. With 44100 calls per second, you'd have 661500 calls.
Each call to toRational allocates several Integers, the calls to 
fromRational even more. I wouldn't expect it to be 4k per wave call, but 
see what figures you get with realToFrac instead of fromRational . 
toRational.

>
>
> "  sinWave  Main   341     1173295 100.0  100.0     0.0    0.0"
> and ~100% of that 75% cpu time is being spent in my callback.
>
> Is there something I'm doing wrong? At the very least, it shouldn't be
> using 3GB of memory. The only thing that needs to be saved between
> callbacks is the IORef, which is storing an Int. I assume that
> evaluating that whole construct in haskell may be too much timewise to
> put in
> a sound callback (or perhaps not), but 3GB of memory is ridiculous.
>
> Thoughts/hints/"you're doing it wrong" anyone?




More information about the Haskell-Cafe mailing list