[Haskell-cafe] Optimizing a high-traffic network architecture

Einar Karttunen ekarttun at cs.helsinki.fi
Wed Dec 14 19:08:09 EST 2005


On 14.12 23:07, Joel Reymont wrote:
> Something like this? Comments are welcome!

> timeout :: Int
> timeout = 5000000 -- 1 second

Is that correct?

> {-# NOINLINE timers #-}
> timers :: MVar Timers
> timers = unsafePerformIO $ newMVar M.empty
> 
> --- Call this first
> initTimers :: IO ()
> initTimers =
>     do forkIO $ block checkTimers
>        return ()

Here is a nice trick for you:

{-# NOINLINE timers #-}
timers :: MVar Timers
timers = unsafePerformIO $ do mv <- newMVar M.empty
                              forkIO $ block checkTimers
                              return mv


initTimers goes thus away.

> --- Not sure if this is the most efficient way to do it
> startTimer :: String -> Int -> (IO ()) -> IO ()
> startTimer name delay io =
>     do stopTimer name
>        now <- getClockTime
>        let plus = TimeDiff 0 0 0 0 0 delay 0
>            future = addToClockTime plus now
>        block $ do t <- takeMVar timers
>                   putMVar timers $ M.insert (future, name) io t

I had code which used a global IORef containing
the current time. It was updated once by a second
by a dedicated thread, but reading it was practically
free. Depends how common getClockTime calls are.

> --- The filter expression is kind of long...
> stopTimer :: String -> IO ()
> stopTimer name =
>     block $ do t <- takeMVar timers
>                putMVar timers $
>                        M.filterWithKey (\(_, k) _ -> k /= name) t

And slow. This is O(size_of_map)

> --- Tried to take care of exceptions here
> --- but the code looks kind of ugly

Is there a reason you need block for checkTimers?
What you certainly want to do is ignore exceptions
from the timer actions.


- Einar Karttunen


More information about the Haskell-Cafe mailing list