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

Edward Amsden eca7215 at cs.rit.edu
Sat Jan 29 17:29:02 CET 2011

I recently got the jack package from hackage working again. For those
unfamiliar, jack is a callback-based audio server.
Writing a client entails importing the C library or its bindings (the
Sound.JACK module in my case), creating a client and
some ports (using provided library functions), and then registering
callbacks for audio processing.

I've written a simple program that outputs a sine wave through JACK.
The server's sample rate is 44100, which means that this function must
be called 44100 times/second (it is buffered, so generally that would
be in chunks of 64, 128, or 256). It is an IO function,
which gives the only opportunity to keep track of time:

(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 $
                  sin (fromIntegral t *

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?

"  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?

Edward Amsden
Computer Science
Rochester Institute of Technology

More information about the Haskell-Cafe mailing list