@@ -1,12 +1,15 @@
11{-# LANGUAGE MagicHash #-}
22
3−import qualified Data.ByteString.Char8 as B8
3+import qualified Data.ByteString.Char8 as BS
4+import qualified Data.ByteString.Lazy.Char8 as BL
5+import qualified Data.ByteString.Lazy.Internal as BL
46import Control.Exception (evaluate)
57import Control.DeepSeq (NFData(..))
68import Criterion.Main
79import Data.Char
810import qualified Codec.Binary.UTF8.Generic as UTF8
9−import qualified Data.Text as T
11+import qualified Data.Text as TS
12+import qualified Data.Text.Lazy as TL
1013import qualified Data.List as L
1114import Data.Text.Encoding
1215import qualified Criterion.MultiMap as M
@@ -21,161 +24,192 @@ myConfig
2124 }
2225 | otherwise = defaultConfig
2326
24−instance NFData B8.ByteString
27+instance NFData BS.ByteString
28+
29+instance NFData BL.ByteString where
30+ rnf BL.Empty = ()
31+ rnf (BL.Chunk _ ts) = rnf ts
2532
2633main = do
27− s0 <- B8.readFile "text/test/russian.txt"
28− let !s0l = B8.length s0
29− t0 = decodeUtf8 s0
30− !t0l = T.length t0
31− l0 = UTF8.toString s0
32− !l0l = L.length l0
33− s1 = B8.map toUpper s0
34− !s1l = B8.length s1
35− t1 = T.toUpper t0
36− !t1l = T.length t1
37− l1 = L.map toUpper l0
38− !l1l = L.length l1
39− sl = B8.lines s0
40− tl = T.lines t0
41− ll = L.lines l0
42− evaluate (rnf (sl,tl,ll))
34+ bsa <- BS.readFile "text/test/russian.txt"
35+ let tsa = decodeUtf8 bsa
36+ tsb = TS.toUpper tsa
37+ tla = TL.fromChunks (TS.chunksOf 16376 tsa)
38+ tlb = TL.fromChunks (TS.chunksOf 16376 tsb)
39+ bsb = encodeUtf8 tsb
40+ bla = BL.fromChunks (chunksOf 16376 bsa)
41+ blb = BL.fromChunks (chunksOf 16376 bsb)
42+ bsa_len = BS.length bsa
43+ tsa_len = TS.length tsa
44+ bla_len = BL.length bla
45+ tla_len = TL.length tla
46+ la = UTF8.toString bsa
47+ la_len = L.length la
48+ tsb_len = TS.length tsb
49+ lb = TS.unpack tsb
50+ bsl = BS.lines bsa
51+ bll = BL.lines bla
52+ tsl = TS.lines tsa
53+ tll = TL.lines tla
54+ ll = L.lines la
4355 defaultMainWith myConfig [
4456 bgroup "append" [
45− bench "text" $ nf (T.append t1) t0
46− , bench "b8" $ nf (B8.append s1) s0
47− , bench "list" $ nf ((++) l1) l0
57+ bench "ts" $ nf (TS.append tsb) tsa
58+ , bench "tl" $ nf (TL.append tlb) tla
59+ , bench "bs" $ nf (BS.append bsb) bsa
60+ , bench "bl" $ nf (BL.append blb) bla
61+ , bench "l" $ nf ((++) lb) la
4862 ],
4963 bgroup "concat" [
50− bench "text" $ nf T.concat tl
51− , bench "b8" $ nf B8.concat sl
52− , bench "list" $ nf L.concat ll
64+ bench "ts" $ nf TS.concat tsl
65+ , bench "tl" $ nf TL.concat tll
66+ , bench "bs" $ nf BS.concat bsl
67+ , bench "bl" $ nf BL.concat bll
68+ , bench "l" $ nf L.concat ll
5369 ],
5470 bgroup "concatMap" [
55− bench "text" $ nf (T.concatMap (T.replicate 3 . T.singleton)) t0
56− , bench "b8" $ nf (B8.concatMap (B8.replicate 3)) s0
57− , bench "list" $ nf (L.concatMap (L.replicate 3 . (:[]))) l0
71+ bench "ts" $ nf (TS.concatMap (TS.replicate 3 . TS.singleton)) tsa
72+ , bench "tl" $ nf (TL.concatMap (TL.replicate 3 . TL.singleton)) tla
73+ , bench "bs" $ nf (BS.concatMap (BS.replicate 3)) bsa
74+ , bench "bl" $ nf (BL.concatMap (BL.replicate 3)) bla
75+ , bench "l" $ nf (L.concatMap (L.replicate 3 . (:[]))) la
5876 ],
5977 bgroup "decode" [
60− bench "text" $ nf decodeUtf8 s0
61− , bench "b8" $ nf B8.unpack s0
62− , bench "utf8-string" $ nf UTF8.toString s0
78+ bench "ts" $ nf decodeUtf8 bsa
79+ , bench "bs" $ nf BS.unpack bsa
80+ , bench "utf8-string" $ nf UTF8.toString bsa
6381 ],
6482 bgroup "drop" [
65− bench "text" $ nf (T.drop (t0l `div` 3)) t0
66− , bench "b8" $ nf (B8.drop (s0l `div` 3)) s0
67− , bench "list" $ nf (L.drop (l0l `div` 3)) l0
83+ bench "ts" $ nf (TS.drop (tsa_len `div` 3)) tsa
84+ , bench "tl" $ nf (TL.drop (tla_len `div` 3)) tla
85+ , bench "bs" $ nf (BS.drop (bsa_len `div` 3)) bsa
86+ , bench "bl" $ nf (BL.drop (bla_len `div` 3)) bla
87+ , bench "l" $ nf (L.drop (la_len `div` 3)) la
6888 ],
6989 bgroup "filter" [
70− bench "text" $ nf (T.filter p0) t0
71− , bench "b8" $ nf (B8.filter p0) s0
72− , bench "list" $ nf (L.filter p0) l0
90+ bench "ts" $ nf (TS.filter p0) tsa
91+ , bench "tl" $ nf (TL.filter p0) tla
92+ , bench "bs" $ nf (BS.filter p0) bsa
93+ , bench "bl" $ nf (BL.filter p0) bla
94+ , bench "l" $ nf (L.filter p0) la
7395 ],
7496 bgroup "2filter" [
75− bench "text" $ nf (T.filter p1 . T.filter p0) t0
76− , bench "b8" $ nf (B8.filter p1 . B8.filter p0) s0
77− , bench "list" $ nf (L.filter p1 . L.filter p0) l0
97+ bench "ts" $ nf (TS.filter p1 . TS.filter p0) tsa
98+ , bench "tl" $ nf (TL.filter p1 . TL.filter p0) tla
99+ , bench "bs" $ nf (BS.filter p1 . BS.filter p0) bsa
100+ , bench "bl" $ nf (BL.filter p1 . BL.filter p0) bla
101+ , bench "l" $ nf (L.filter p1 . L.filter p0) la
78102 ],
79103 bgroup "foldl'" [
80− bench "text" $ nf (T.foldl' len 0) t0
81− , bench "b8" $ nf (B8.foldl' len 0) s0
82− , bench "list" $ nf (L.foldl' len 0) l0
104+ bench "ts" $ nf (TS.foldl' len 0) tsa
105+ , bench "tl" $ nf (TL.foldl' len 0) tla
106+ , bench "bs" $ nf (BS.foldl' len 0) bsa
107+ , bench "bl" $ nf (BL.foldl' len 0) bla
108+ , bench "l" $ nf (L.foldl' len 0) la
83109 ],
84110 bgroup "foldr" [
85− bench "text" $ nf (L.length . T.foldr (:) []) t0
86− , bench "b8" $ nf (L.length . B8.foldr (:) []) s0
87− , bench "list" $ nf (L.length . L.foldr (:) []) l0
111+ bench "ts" $ nf (L.length . TS.foldr (:) []) tsa
112+ , bench "tl" $ nf (L.length . TL.foldr (:) []) tla
113+ , bench "bs" $ nf (L.length . BS.foldr (:) []) bsa
114+ , bench "bl" $ nf (L.length . BL.foldr (:) []) bla
115+ , bench "l" $ nf (L.length . L.foldr (:) []) la
88116 ],
89117 bgroup "intercalate" [
90− bench "text" $ nf (T.intercalate tw) tl
91− , bench "b8" $ nf (B8.intercalate sw) sl
92− , bench "list" $ nf (L.intercalate lw) ll
118+ bench "ts" $ nf (TS.intercalate tsw) tsl
119+ , bench "tl" $ nf (TL.intercalate tlw) tll
120+ , bench "bs" $ nf (BS.intercalate bsw) bsl
121+ , bench "bl" $ nf (BL.intercalate blw) bll
122+ , bench "l" $ nf (L.intercalate lw) ll
93123 ],
94124 bgroup "isInfixOf" [
95− bench "text" $ nf (T.isInfixOf tw) t0
96− , bench "b8" $ nf (B8.isInfixOf sw) s0
97− , bench "list" $ nf (L.isInfixOf lw) l0
125+ bench "ts" $ nf (TS.isInfixOf tsw) tsa
126+ , bench "tl" $ nf (TL.isInfixOf tlw) tla
127+ , bench "bs" $ nf (BS.isInfixOf bsw) bsa
128+ -- no isInfixOf for lazy bytestrings
129+ , bench "l" $ nf (L.isInfixOf lw) la
98130 ],
99131 bgroup "last" [
100− bench "text" $ nf T.last t0
101− , bench "b8" $ nf B8.last s0
102− , bench "list" $ nf L.last l0
132+ bench "ts" $ nf TS.last tsa
133+ , bench "tl" $ nf TL.last tla
134+ , bench "bs" $ nf BS.last bsa
135+ , bench "bl" $ nf BL.last bla
136+ , bench "l" $ nf L.last la
103137 ],
104138 bgroup "map" [
105− bench "text" $ nf (T.map f) t0
106− , bench "b8" $ nf (B8.map f) s0
107− , bench "list" $ nf (L.map f) l0
139+ bench "ts" $ nf (TS.map f) tsa
140+ , bench "bs" $ nf (BS.map f) bsa
141+ , bench "l" $ nf (L.map f) la
108142 ],
109143 bgroup "2map" [
110− bench "text" $ nf (T.map f . T.map f) t0
111− , bench "b8" $ nf (B8.map f . B8.map f) s0
112− , bench "list" $ nf (L.map f . L.map f) l0
144+ bench "ts" $ nf (TS.map f . TS.map f) tsa
145+ , bench "bs" $ nf (BS.map f . BS.map f) bsa
146+ , bench "l" $ nf (L.map f . L.map f) la
113147 ],
114148 bgroup "reverse" [
115− bench "text" $ nf T.reverse t0
116− , bench "b8" $ nf B8.reverse s0
117− , bench "list" $ nf L.reverse l0
149+ bench "ts" $ nf TS.reverse tsa
150+ , bench "bs" $ nf BS.reverse bsa
151+ , bench "l" $ nf L.reverse la
118152 ],
119153 bgroup "take" [
120− bench "text" $ nf (T.take (t0l `div` 3)) t0
121− , bench "b8" $ nf (B8.take (s0l `div` 3)) s0
122− , bench "list" $ nf (L.take (l0l `div` 3)) l0
154+ bench "ts" $ nf (TS.take (tsa_len `div` 3)) tsa
155+ , bench "bs" $ nf (BS.take (bsa_len `div` 3)) bsa
156+ , bench "l" $ nf (L.take (la_len `div` 3)) la
123157 ],
124158 bgroup "words" [
125− bench "text" $ nf T.words t0
126− , bench "b8" $ nf B8.words s0
127− , bench "list" $ nf L.words l0
159+ bench "ts" $ nf TS.words tsa
160+ , bench "bs" $ nf BS.words bsa
161+ , bench "l" $ nf L.words la
128162 ],
129163 bgroup "zipWith" [
130− bench "text" $ nf (T.zipWith min t1) t0
131− , bench "b8" $ nf (B8.zipWith min s1) s0
132− , bench "list" $ nf (L.zipWith min l1) l0
164+ bench "ts" $ nf (TS.zipWith min tsb) tsa
165+ , bench "bs" $ nf (BS.zipWith min bsb) bsa
166+ , bench "l" $ nf (L.zipWith min lb) la
133167 ],
134168 bgroup "length" [
135169 bgroup "decode" [
136− bench "text" $ nf (T.length . decodeUtf8) s0
137− , bench "b8" $ nf (L.length . B8.unpack) s0
138− , bench "utf8-string" $ nf (L.length . UTF8.toString) s0
170+ bench "ts" $ nf (TS.length . decodeUtf8) bsa
171+ , bench "bs" $ nf (L.length . BS.unpack) bsa
172+ , bench "utf8-string" $ nf (L.length . UTF8.toString) bsa
139173 ],
140174 bgroup "drop" [
141− bench "text" $ nf (T.length . T.drop (t0l `div` 3)) t0
142− , bench "b8" $ nf (B8.length . B8.drop (s0l `div` 3)) s0
143− , bench "list" $ nf (L.length . L.drop (l0l `div` 3)) l0
175+ bench "ts" $ nf (TS.length . TS.drop (tsa_len `div` 3)) tsa
176+ , bench "bs" $ nf (BS.length . BS.drop (bsa_len `div` 3)) bsa
177+ , bench "l" $ nf (L.length . L.drop (la_len `div` 3)) la
144178 ],
145179 bgroup "filter" [
146− bench "text" $ nf (T.length . T.filter p0) t0
147− , bench "b8" $ nf (B8.length . B8.filter p0) s0
148− , bench "list" $ nf (L.length . L.filter p0) l0
180+ bench "ts" $ nf (TS.length . TS.filter p0) tsa
181+ , bench "bs" $ nf (BS.length . BS.filter p0) bsa
182+ , bench "l" $ nf (L.length . L.filter p0) la
149183 ],
150184 bgroup "2filter" [
151− bench "text" $ nf (T.length . T.filter p1 . T.filter p0) t0
152− , bench "b8" $ nf (B8.length . B8.filter p1 . B8.filter p0) s0
153− , bench "list" $ nf (L.length . L.filter p1 . L.filter p0) l0
185+ bench "ts" $ nf (TS.length . TS.filter p1 . TS.filter p0) tsa
186+ , bench "bs" $ nf (BS.length . BS.filter p1 . BS.filter p0) bsa
187+ , bench "l" $ nf (L.length . L.filter p1 . L.filter p0) la
154188 ],
155189 bgroup "map" [
156− bench "text" $ nf (T.length . T.map f) t0
157− , bench "b8" $ nf (B8.length . B8.map f) s0
158− , bench "list" $ nf (L.length . L.map f) l0
190+ bench "ts" $ nf (TS.length . TS.map f) tsa
191+ , bench "bs" $ nf (BS.length . BS.map f) bsa
192+ , bench "l" $ nf (L.length . L.map f) la
159193 ],
160194 bgroup "2map" [
161− bench "text" $ nf (T.length . T.map f . T.map f) t0
162− , bench "b8" $ nf (B8.length . B8.map f . B8.map f) s0
163− , bench "list" $ nf (L.length . L.map f . L.map f) l0
195+ bench "ts" $ nf (TS.length . TS.map f . TS.map f) tsa
196+ , bench "bs" $ nf (BS.length . BS.map f . BS.map f) bsa
197+ , bench "l" $ nf (L.length . L.map f . L.map f) la
164198 ],
165199 bgroup "take" [
166− bench "text" $ nf (T.length . T.take (t0l `div` 3)) t0
167− , bench "b8" $ nf (B8.length . B8.take (s0l `div` 3)) s0
168− , bench "list" $ nf (L.length . L.take (l0l `div` 3)) l0
200+ bench "ts" $ nf (TS.length . TS.take (tsa_len `div` 3)) tsa
201+ , bench "bs" $ nf (BS.length . BS.take (bsa_len `div` 3)) bsa
202+ , bench "l" $ nf (L.length . L.take (la_len `div` 3)) la
169203 ],
170204 bgroup "words" [
171− bench "text" $ nf (L.length . T.words) t0
172− , bench "b8" $ nf (L.length . B8.words) s0
173− , bench "list" $ nf (L.length . L.words) l0
205+ bench "ts" $ nf (L.length . TS.words) tsa
206+ , bench "bs" $ nf (L.length . BS.words) bsa
207+ , bench "l" $ nf (L.length . L.words) la
174208 ],
175209 bgroup "zipWith" [
176− bench "text" $ nf (T.length . T.zipWith min t1) t0
177− , bench "b8" $ nf (L.length . B8.zipWith min s1) s0
178− , bench "list" $ nf (L.length . L.zipWith min l1) l0
210+ bench "ts" $ nf (TS.length . TS.zipWith min tsb) tsa
211+ , bench "bs" $ nf (L.length . BS.zipWith min bsb) bsa
212+ , bench "l" $ nf (L.length . L.zipWith min lb) la
179213 ]
180214 ]
181215 ]
@@ -183,7 +217,16 @@ main = do
183217 p0 = (== 'й')
184218 p1 = (/= 'д')
185219 lw = "право"
186− sw = UTF8.fromString lw
187− tw = T.pack lw
220+ bsw = UTF8.fromString lw
221+ blw = BL.fromChunks [bsw]
222+ tsw = TS.pack lw
223+ tlw = TL.fromChunks [tsw]
188224 f (C# c#) = C# (chr# (ord# c# +# 1#))
189225 len l _ = l + (1::Int)
226+
227+chunksOf :: Int -> BS.ByteString -> [BS.ByteString]
228+chunksOf k = go
229+ where
230+ go t = case BS.splitAt k t of
231+ (a,b) | BS.null a -> []
232+ | otherwise -> a : go b