Skip to content

Commit bf8ad02

Browse files
committed
faster toBytes
1 parent 0461bfc commit bf8ad02

File tree

2 files changed

+71
-7
lines changed

2 files changed

+71
-7
lines changed

bench/src/Bench.hs

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import Data.BitCode
66
import Data.BitCode.Writer (emitTopLevel)
77
import Data.BitCode.Writer.Monad (writeFile)
88
import Data.BitCode.Writer.Combinators (withHeader)
9+
import Data.Word (Word8)
10+
import Data.Bits (FiniteBits, setBit, zeroBits)
911

1012
import Criterion.Main
1113

@@ -17,9 +19,52 @@ readModule = decodeFile
1719
writeModule :: FilePath -> [BitCode] -> IO ()
1820
writeModule f = writeFile f . withHeader True . emitTopLevel
1921

22+
--------------------------------------------------------------------------------
23+
-- Turing a stream of Bits into Bytes
24+
-- type Bits = [Bool]
25+
26+
partition :: Int -> Bits -> [Bits]
27+
partition _ [] = []
28+
partition n xs | length xs < n = [xs]
29+
partition n xs | otherwise = h:partition n t
30+
where (h,t) = (take n xs, drop n xs)
31+
32+
toBytes :: Bits -> [Word8]
33+
toBytes = map toFiniteBits . partition 8
34+
where toFiniteBits :: (FiniteBits a) => Bits -> a
35+
toFiniteBits = foldl setBit zeroBits . map fst . filter ((== True) . snd) . zip [0..]
36+
37+
38+
39+
toBytes2 :: Bits -> [Word8]
40+
toBytes2 = go
41+
where
42+
go (b0:b1:b2:b3:b4:b5:b6:b7:rest) =
43+
let byte =
44+
theBit 0 b0
45+
$ theBit 1 b1
46+
$ theBit 2 b2
47+
$ theBit 3 b3
48+
$ theBit 4 b4
49+
$ theBit 5 b5
50+
$ theBit 6 b6
51+
$ theBit 7 b7
52+
zeroBits
53+
in byte : go rest
54+
where
55+
theBit :: Int -> Bool -> Word8 -> Word8
56+
theBit n True = flip setBit n
57+
theBit _ False = id
58+
go [] = []
59+
go bs = go (take 8 $ bs ++ [False, False, False, False
60+
,False, False, False, False])
61+
2062
main :: IO ()
2163
main = defaultMain [
22-
bgroup "writer"
23-
[ bench "HelloWorld" $ nfIO (writeModule "HelloWorld.bc" =<< readModule "bench/data/HelloWorld.mod")
24-
, bench "HelloWorld2" $ nfIO (writeModule "HelloWorld2.bc" =<< readModule "bench/data/HelloWorld2.mod")
25-
]]
64+
-- bgroup "writer"
65+
-- [ bench "HelloWorld" $ nfIO (writeModule "HelloWorld.bc" =<< readModule "bench/data/HelloWorld.mod")
66+
-- , bench "HelloWorld2" $ nfIO (writeModule "HelloWorld2.bc" =<< readModule "bench/data/HelloWorld2.mod")
67+
-- ]
68+
bgroup "toBytes" [ bench (show i) $ nf toBytes [False | _ <- [1..i]] | i <- [8000,16000..96000] ]
69+
, bgroup "toBytes2" [ bench (show i) $ nf toBytes2 [False | _ <- [1..i]] | i <- [8000,16000..96000] ]
70+
]

src/Data/BitCode/Writer/Monad.hs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,35 @@ ask :: BitCodeWriter (Int, Int)
8585
ask = BitCode $ \b@(BitC ws bs _) -> ((ws,bs),b)
8686

8787
-- * Utility
88+
8889
partition :: Int -> Bits -> [Bits]
8990
partition _ [] = []
9091
partition n xs | length xs < n = [xs]
9192
partition n xs | otherwise = h:partition n t
9293
where (h,t) = (take n xs, drop n xs)
9394

9495
toBytes :: Bits -> [Word8]
95-
toBytes = map toFiniteBits . partition 8
96-
where toFiniteBits :: (FiniteBits a) => Bits -> a
97-
toFiniteBits = foldl setBit zeroBits . map fst . filter ((== True) . snd) . zip [0..]
96+
toBytes = go
97+
where
98+
go (b0:b1:b2:b3:b4:b5:b6:b7:rest) =
99+
let byte =
100+
theBit 0 b0
101+
$ theBit 1 b1
102+
$ theBit 2 b2
103+
$ theBit 3 b3
104+
$ theBit 4 b4
105+
$ theBit 5 b5
106+
$ theBit 6 b6
107+
$ theBit 7 b7
108+
zeroBits
109+
in byte : go rest
110+
where
111+
theBit :: Int -> Bool -> Word8 -> Word8
112+
theBit n True = flip setBit n
113+
theBit _ False = id
114+
go [] = []
115+
go bs = go (take 8 $ bs ++ [False, False, False, False
116+
,False, False, False, False])
98117

99118
-- * Writing out to file.
100119
writeFile :: FilePath -> BitCodeWriter () -> IO ()

0 commit comments

Comments
 (0)