1+ import Control.DeepSeq (NFData , deepseq )
2+ import Data.Ix (Ix (.. ))
3+ import Test.Tasty.Bench (Benchmark , bgroup , bench , bcompare , nf , defaultMain )
4+
5+ import qualified Data.Char as B
6+ import qualified Unicode.Char.Case as C
7+ import qualified Unicode.Char.General as G
8+ import qualified Unicode.Char.General.Compat as GC
9+ import qualified Unicode.Char.Identifiers as I
10+ import qualified Unicode.Char.Normalization as N
11+ import qualified Unicode.Char.Numeric as Num
12+
13+ -- | A unit benchmark
14+ data Bench a = Bench
15+ { _title :: ! String -- ^ Name
16+ , _func :: Char -> a -- ^ Function to benchmark
17+ }
18+
19+ main :: IO ()
20+ main = defaultMain
21+ [ bgroup " Unicode.Char.Case"
22+ [ bgroup' " isLower"
23+ [ Bench " base" B. isLower
24+ , Bench " unicode-data" C. isLower
25+ ]
26+ , bgroup' " isUpper"
27+ [ Bench " base" B. isUpper
28+ , Bench " unicode-data" C. isUpper
29+ ]
30+ ]
31+ , bgroup " Unicode.Char.General"
32+ -- Character classification
33+ [ bgroup' " generalCategory"
34+ [ Bench " base" (show . B. generalCategory)
35+ , Bench " unicode-data" (show . G. generalCategory)
36+ ]
37+ , bgroup " isAlphabetic"
38+ [ benchNF " unicode-data" G. isAlphabetic
39+ ]
40+ , bgroup' " isAlphaNum"
41+ [ Bench " base" B. isAlphaNum
42+ , Bench " unicode-data" G. isAlphaNum
43+ ]
44+ , bgroup' " isControl"
45+ [ Bench " base" B. isControl
46+ , Bench " unicode-data" G. isControl
47+ ]
48+ , bgroup' " isMark"
49+ [ Bench " base" B. isMark
50+ , Bench " unicode-data" G. isMark
51+ ]
52+ , bgroup' " isPrint"
53+ [ Bench " base" B. isPrint
54+ , Bench " unicode-data" G. isPrint
55+ ]
56+ , bgroup' " isPunctuation"
57+ [ Bench " base" B. isPunctuation
58+ , Bench " unicode-data" G. isPunctuation
59+ ]
60+ , bgroup' " isSeparator"
61+ [ Bench " base" B. isSeparator
62+ , Bench " unicode-data" G. isSeparator
63+ ]
64+ , bgroup' " isSymbol"
65+ [ Bench " base" B. isSymbol
66+ , Bench " unicode-data" G. isSymbol
67+ ]
68+ , bgroup " isWhiteSpace"
69+ [ benchNF " unicode-data" G. isWhiteSpace
70+ ]
71+ -- Korean Hangul Characters
72+ , bgroup " isHangul"
73+ [ benchNF " unicode-data" G. isHangul
74+ ]
75+ , bgroup " isHangulLV"
76+ [ benchNF " unicode-data" G. isHangul
77+ ]
78+ , bgroup " isJamo"
79+ [ benchNF " unicode-data" G. isJamo
80+ ]
81+ , bgroup " jamoLIndex"
82+ [ benchNF " unicode-data" G. jamoLIndex
83+ ]
84+ , bgroup " jamoVIndex"
85+ [ benchNF " unicode-data" G. jamoVIndex
86+ ]
87+ , bgroup " jamoTIndex"
88+ [ benchNF " unicode-data" G. jamoTIndex
89+ ]
90+ ]
91+ , bgroup " Unicode.Char.General.Compat"
92+ [ bgroup' " isAlpha"
93+ [ Bench " base" B. isAlpha
94+ , Bench " unicode-data" GC. isAlpha
95+ ]
96+ , bgroup' " isLetter"
97+ [ Bench " base" B. isLetter
98+ , Bench " unicode-data" GC. isLetter
99+ ]
100+ , bgroup' " isSpace"
101+ [ Bench " base" B. isSpace
102+ , Bench " unicode-data" GC. isSpace
103+ ]
104+ ]
105+ , bgroup " Unicode.Char.Identifiers"
106+ [ bgroup " isIDContinue"
107+ [ benchNF " unicode-data" I. isIDContinue
108+ ]
109+ , bgroup " isIDStart"
110+ [ benchNF " unicode-data" I. isIDStart
111+ ]
112+ , bgroup " isXIDContinue"
113+ [ benchNF " unicode-data" I. isXIDContinue
114+ ]
115+ , bgroup " isXIDStart"
116+ [ benchNF " unicode-data" I. isXIDStart
117+ ]
118+ , bgroup " isPatternSyntax"
119+ [ benchNF " unicode-data" I. isPatternSyntax
120+ ]
121+ , bgroup " isPatternWhitespace"
122+ [ benchNF " unicode-data" I. isPatternWhitespace
123+ ]
124+ ]
125+ , bgroup " Unicode.Char.Normalization"
126+ [ bgroup " isCombining"
127+ [ benchNF " unicode-data" N. isCombining
128+ ]
129+ , bgroup " combiningClass"
130+ [ benchNF " unicode-data" N. combiningClass
131+ ]
132+ , bgroup " isCombiningStarter"
133+ [ benchNF " unicode-data" N. isCombiningStarter
134+ ]
135+ -- [TODO] compose, composeStarters
136+ , bgroup " isDecomposable"
137+ [ bgroup " Canonical"
138+ [ benchNF " unicode-data" (N. isDecomposable N. Canonical )
139+ ]
140+ , bgroup " Kompat"
141+ [ benchNF " unicode-data" (N. isDecomposable N. Kompat )
142+ ]
143+ ]
144+ -- [FIXME] Fail due to non-exhaustive pattern matching
145+ -- , bgroup "decompose"
146+ -- [ bgroup "Canonical"
147+ -- [ benchNF "unicode-data" (N.decompose N.Canonical)
148+ -- ]
149+ -- , bgroup "Kompat"
150+ -- [ benchNF "unicode-data" (N.decompose N.Kompat)
151+ -- ]
152+ -- ]
153+ , bgroup " decomposeHangul"
154+ [ benchNF " unicode-data" N. decomposeHangul
155+ ]
156+ ]
157+ , bgroup " Unicode.Char.Numeric"
158+ [ bgroup' " isNumber"
159+ [ Bench " base" B. isNumber
160+ , Bench " unicode-data" Num. isNumber
161+ ]
162+ ]
163+ ]
164+ where
165+ bgroup' groupTitle bs = bgroup groupTitle
166+ [ benchNF' groupTitle title f
167+ | Bench title f <- bs
168+ ]
169+
170+ -- [NOTE] Works if groupTitle uniquely identifies the benchmark group.
171+ benchNF' groupTitle title = case title of
172+ " base" -> benchNF title
173+ _ -> bcompare (" $NF == \" base\" && $(NF-1) == \" " ++ groupTitle ++ " \" " )
174+ . benchNF title
175+
176+ benchNF :: forall a . (NFData a ) => String -> (Char -> a ) -> Benchmark
177+ benchNF t f = bench t $ nf (fold_ f) (minBound , maxBound )
178+
179+ fold_ :: forall a . (NFData a ) => (Char -> a ) -> (Char , Char ) -> ()
180+ fold_ f = foldr (deepseq . f) () . range
0 commit comments