{-# LANGUAGE ExistentialQuantification #-}
import Control.DeepSeq (NFData, deepseq)
import Data.Ix (Ix(..))
import Test.Tasty.Bench (Benchmark, bgroup, bcompare, bench, nf, defaultMain)
import qualified Unicode.Char.General.Names as Names
import qualified Unicode.Internal.Char.UnicodeData.DerivedName as DerivedName
import qualified Unicode.Internal.Char.UnicodeData.NameAliases as NameAliases
-- | A unit benchmark
data Bench = forall a. (NFData a) => Bench
{ _title :: !String -- ^ Name
, _func :: Char -> a -- ^ Function to benchmark
}
main :: IO ()
main = defaultMain
[ bgroup "Unicode.Char.General.Names"
-- Character classification
[ bgroup' "name"
[ Bench "CString" DerivedName.name
, Bench "String" Names.name
]
, bgroup' "correctedName"
[ Bench "String" Names.correctedName
]
, bgroup' "nameOrAlias"
[ Bench "String" Names.name
]
, bgroup' "nameAliasesByType"
[ Bench "CString"
(\c -> (`NameAliases.nameAliasesByType` c) <$> [minBound..maxBound])
, Bench "String"
(\c -> (`Names.nameAliasesByType` c) <$> [minBound..maxBound])
]
, bgroup' "nameAliasesWithTypes"
[ Bench "CString" (show . NameAliases.nameAliasesWithTypes)
, Bench "String" (show . Names.nameAliasesWithTypes)
]
]
]
where
bgroup' groupTitle bs = bgroup groupTitle
[ benchNF' groupTitle title f
| Bench title f <- bs
]
-- [NOTE] Works if groupTitle uniquely identifies the benchmark group.
benchNF' groupTitle title = case title of
"CString" -> benchNF title
_ ->
bcompare ("$NF == \"CString\" && $(NF-1) == \"" ++ groupTitle ++ "\"")
. benchNF title
benchNF :: forall a. (NFData a) => String -> (Char -> a) -> Benchmark
benchNF t f = bench t $ nf (fold_ f) (minBound, maxBound)
fold_ :: forall a. (NFData a) => (Char -> a) -> (Char, Char) -> ()
fold_ f = foldr (deepseq . f) () . range