dictionaries-0.2.0: tests/Benchmark.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE BangPatterns #-}
import Control.DeepSeq (NFData(..))
import Control.Monad.Catch (MonadThrow)
import Control.Monad.IO.Class (MonadIO)
import Criterion (Benchmark, bench, nfIO, env)
import Criterion.Main (bgroup, defaultMain)
import Data.List (intercalate)
import NLP.Dictionary (Dictionary(..))
import NLP.Dictionary.StarDict (StarDict(..))
import NLP.Dictionary.StarDict.Common (IfoFilePath)
import System.Random (getStdGen)
import System.Random.Shuffle (shuffle')
import Utils (generateDictionary, generateStarDict, renderId)
import qualified NLP.Dictionary.StarDict.Regular as SDR
import qualified NLP.Dictionary.StarDict.InMemory as SDIM
data DictionaryWrapper = forall d. (NFData d, Dictionary d) => WrapDictionary d
wrapDictionary :: (NFData d, Dictionary d) => d -> DictionaryWrapper
wrapDictionary = WrapDictionary
instance Dictionary DictionaryWrapper where
getEntries name (WrapDictionary d) = getEntries name d
instance NFData DictionaryWrapper where
rnf (WrapDictionary !_) = ()
data DictionaryType
= Regular
| InMemory
deriving (Eq, Show, Enum, Bounded)
mkWrappedDictionary :: (MonadIO m, MonadThrow m)
=> DictionaryType
-> IfoFilePath
-> m DictionaryWrapper
mkWrappedDictionary Regular = \p -> wrapDictionary <$> mkDictionary (SDR.tag p) renderId
mkWrappedDictionary InMemory = \p -> wrapDictionary <$> mkDictionary (SDIM.tag p) renderId
around :: Int -> (Int, Int)
around x = let dx = min (x `div` 10) 1 in (x - dx, x + dx)
mkName :: Int -> Int -> Int -> String
mkName dictionarySize textSize wordSize = intercalate "_" $ [
show dictionarySize
, show textSize
, show wordSize
]
benchLoading :: Int -> Int -> Int -> DictionaryType -> Benchmark
benchLoading dictionarySize textSize wordSize dictionaryType = env
(generateDictionary
dictionarySize
(around textSize)
(around wordSize)
>>= generateStarDict)
$ \starDictPath -> bench (mkName dictionarySize textSize wordSize) $ do
nfIO $ (mkWrappedDictionary dictionaryType starDictPath)
benchAccessing :: Int -> Int -> Int -> DictionaryType -> Benchmark
benchAccessing dictionarySize textSize wordSize dictionaryType = env
(do
dict <- generateDictionary
dictionarySize
(around textSize)
(around wordSize)
sampleWords <- fmap (take 10)
. fmap (shuffle' (map fst dict) (length dict))
$ getStdGen
starDict <- generateStarDict dict >>= mkWrappedDictionary dictionaryType
return (starDict, sampleWords))
$ \ ~(starDict, sampleWords) -> bench (mkName dictionarySize textSize wordSize) $ do
nfIO $ mapM (flip getEntries starDict) sampleWords
benchDictionaries :: ([DictionaryType -> Benchmark]) -> [Benchmark]
benchDictionaries bs = map
(\dt -> bgroup (show dt) (map ($ dt) bs))
[minBound..maxBound]
main :: IO ()
main = defaultMain [
bgroup "Loading" . benchDictionaries $ [
benchLoading 100 100 100
, benchLoading 500 100 100
, benchLoading 100 500 100
, benchLoading 100 100 500
]
, bgroup "Accessing" . benchDictionaries $ [
benchAccessing 100 100 100
, benchAccessing 500 100 100
, benchAccessing 100 500 100
, benchAccessing 100 100 500
]
]