[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