{-# LANGUAGE BangPatterns #-}
module Main where
import Control.Concurrent.TokenBucket
import Control.Concurrent
import Control.Exception
import Control.Monad
import Data.Time.Clock.POSIX (getPOSIXTime)
import System.Exit
import Data.Word
getPosixTime :: IO Double
getPosixTime = fmap realToFrac getPOSIXTime
toInvRate :: Double -> Word64
toInvRate r = round (1e6 / r)
timeIO :: IO a -> IO (Double, a)
timeIO act = do
ts0 <- getPosixTime
res <- act
ts1 <- getPosixTime
dt <- evaluate (ts1-ts0)
return (dt,res)
timeIO_ :: IO a -> IO Double
timeIO_ = fmap fst . timeIO
main :: IO ()
main = runInUnboundThread $ do
putStrLn "testing tocket-bucket..."
!tb <- newTokenBucket
replicateM_ 3 $ do
check tb 10 10.0
check tb 20 20.0
check tb 50 50.0
check tb 100 100.0
check tb 200 200.0
check tb 500 500.0
check tb 1000 1000.0
putStrLn "============================================="
where
check :: TokenBucket -> Int -> Double -> IO ()
check tb n rate = do
-- threadDelay 100000
putStrLn $ "running "++show n++"+1 iterations with "++show rate++" Hz rate-limit..."
dt <- timeIO_ (replicateM_ (n+1) $ (tokenBucketWait tb 1 (toInvRate rate)))
let rate' = fromIntegral n/dt
unless (rate' <= rate) $ do
putStrLn $ "...FAILED! (effective rate was " ++ show rate' ++ " Hz)"
exitFailure
putStrLn $ "...PASSED (effective rate was " ++ show rate' ++ " Hz)"