1{-# LANGUAGE OverloadedStrings #-} 2-- | 3-- Module : ChunkedWrite 4-- Copyright : (c) 2010 Simon Meier 5-- License : BSD3-style (see LICENSE) 6-- 7-- Maintainer : Leon P Smith <leon@melding-monads.com> 8-- Stability : experimental 9-- Portability : tested on GHC only 10-- 11-- Test different strategies for writing lists of simple values: 12-- 13-- 1. Using 'mconcat . map from<Value>' 14-- 15-- 2. Using the specialized 'fromWrite<n>List' function where 'n' denotes 16-- the number of elements to write at the same time. Writing chunks of 17-- elements reduces the overhead from the buffer overflow test that has 18-- to be done before every write. 19-- 20module ChunkedWrite where 21 22import Data.Char (chr) 23import Data.Int (Int64) 24import Data.Word (Word8, Word32) 25import Data.Monoid 26 27import Criterion.Main 28import qualified Data.ByteString.Lazy as L 29import qualified Data.ByteString as S 30 31import qualified Blaze.ByteString.Builder as BB 32import qualified Blaze.ByteString.Builder.Char.Utf8 as BB 33 34main :: IO () 35main = defaultMain 36 [ bench "S.pack: [Word8] -> S.ByteString" $ 37 whnf (S.pack) word8s 38 39 , bench "toByteString . fromWord8s: [Word8] -> Builder -> S.ByteString" $ 40 whnf (BB.toByteString . BB.fromWord8s) word8s 41 42 , bench "L.pack: [Word8] -> L.ByteString" $ 43 whnf (L.length . L.pack) word8s 44 45 , bench "mconcat . map fromByte: [Word8] -> Builder -> L.ByteString" $ 46 whnf benchMConcatWord8s word8s 47 , bench "fromWrite1List: [Word8] -> Builder -> L.ByteString" $ 48 whnf bench1Word8s word8s 49 , bench "fromWrite2List: [Word8] -> Builder -> L.ByteString" $ 50 whnf bench2Word8s word8s 51 , bench "fromWrite4List: [Word8] -> Builder -> L.ByteString" $ 52 whnf bench4Word8s word8s 53 , bench "fromWrite8List: [Word8] -> Builder -> L.ByteString" $ 54 whnf bench8Word8s word8s 55 , bench "fromWrite16List: [Word8] -> Builder -> L.ByteString" $ 56 whnf bench16Word8s word8s 57 58 , bench "mconcat . map fromByte: [Char] -> Builder -> L.ByteString" $ 59 whnf benchMConcatChars chars 60 , bench "fromWrite1List: [Char] -> Builder -> L.ByteString" $ 61 whnf bench1Chars chars 62 , bench "fromWrite2List: [Char] -> Builder -> L.ByteString" $ 63 whnf bench2Chars chars 64 , bench "fromWrite4List: [Char] -> Builder -> L.ByteString" $ 65 whnf bench4Chars chars 66 , bench "fromWrite8List: [Char] -> Builder -> L.ByteString" $ 67 whnf bench8Chars chars 68 , bench "fromWrite16List: [Char] -> Builder -> L.ByteString" $ 69 whnf bench16Chars chars 70 71 , bench "mconcat . map fromWord32host: [Word32] -> Builder -> L.ByteString" $ 72 whnf benchMConcatWord32s word32s 73 , bench "fromWrite1List: [Word32] -> Builder -> L.ByteString" $ 74 whnf bench1Word32s word32s 75 , bench "fromWrite2List: [Word32] -> Builder -> L.ByteString" $ 76 whnf bench2Word32s word32s 77 , bench "fromWrite4List: [Word32] -> Builder -> L.ByteString" $ 78 whnf bench4Word32s word32s 79 , bench "fromWrite8List: [Word32] -> Builder -> L.ByteString" $ 80 whnf bench8Word32s word32s 81 , bench "fromWrite16List: [Word32] -> Builder -> L.ByteString" $ 82 whnf bench16Word32s word32s 83 ] 84 where 85 n = 100000 86 87 word8s :: [Word8] 88 word8s = take n $ map fromIntegral $ [(1::Int)..] 89 {-# NOINLINE word8s #-} 90 91 word32s :: [Word32] 92 word32s = take n $ [1..] 93 {-# NOINLINE word32s #-} 94 95 chars :: String 96 chars = take n $ map (chr . fromIntegral) $ word8s 97 {-# NOINLINE chars #-} 98 99-- Char 100 101benchMConcatChars :: [Char] -> Int64 102benchMConcatChars = L.length . BB.toLazyByteString . mconcat . map BB.fromChar 103 104bench1Chars :: [Char] -> Int64 105bench1Chars = L.length . BB.toLazyByteString . BB.fromWrite1List BB.writeChar 106 107bench2Chars :: [Char] -> Int64 108bench2Chars = L.length . BB.toLazyByteString . BB.fromWrite2List BB.writeChar 109 110bench4Chars :: [Char] -> Int64 111bench4Chars = L.length . BB.toLazyByteString . BB.fromWrite4List BB.writeChar 112 113bench8Chars :: [Char] -> Int64 114bench8Chars = L.length . BB.toLazyByteString . BB.fromWrite8List BB.writeChar 115 116bench16Chars :: [Char] -> Int64 117bench16Chars = L.length . BB.toLazyByteString . BB.fromWrite16List BB.writeChar 118 119-- Word8 120 121benchMConcatWord8s :: [Word8] -> Int64 122benchMConcatWord8s = L.length . BB.toLazyByteString . mconcat . map BB.fromWord8 123 124bench1Word8s :: [Word8] -> Int64 125bench1Word8s = L.length . BB.toLazyByteString . BB.fromWrite1List BB.writeWord8 126 127bench2Word8s :: [Word8] -> Int64 128bench2Word8s = L.length . BB.toLazyByteString . BB.fromWrite2List BB.writeWord8 129 130bench4Word8s :: [Word8] -> Int64 131bench4Word8s = L.length . BB.toLazyByteString . BB.fromWrite4List BB.writeWord8 132 133bench8Word8s :: [Word8] -> Int64 134bench8Word8s = L.length . BB.toLazyByteString . BB.fromWrite8List BB.writeWord8 135 136bench16Word8s :: [Word8] -> Int64 137bench16Word8s = L.length . BB.toLazyByteString . BB.fromWrite16List BB.writeWord8 138 139-- Word32 140 141benchMConcatWord32s :: [Word32] -> Int64 142benchMConcatWord32s = L.length . BB.toLazyByteString . mconcat . map BB.fromWord32host 143 144bench1Word32s :: [Word32] -> Int64 145bench1Word32s = L.length . BB.toLazyByteString . BB.fromWrite1List BB.writeWord32host 146 147bench2Word32s :: [Word32] -> Int64 148bench2Word32s = L.length . BB.toLazyByteString . BB.fromWrite2List BB.writeWord32host 149 150bench4Word32s :: [Word32] -> Int64 151bench4Word32s = L.length . BB.toLazyByteString . BB.fromWrite4List BB.writeWord32host 152 153bench8Word32s :: [Word32] -> Int64 154bench8Word32s = L.length . BB.toLazyByteString . BB.fromWrite8List BB.writeWord32host 155 156bench16Word32s :: [Word32] -> Int64 157bench16Word32s = L.length . BB.toLazyByteString . BB.fromWrite16List BB.writeWord32host 158 159