on master help sign in
Add some SCC annotations, and try to improve performance.
fe7b48bBryan O'Sullivan
Data/Aeson/Encode.hs+33−23
@@ -17,13 +17,15 @@ module Data.Aeson.Encode
17 , encode
17 , encode
18 ) where
18 ) where
19
19
20−import Blaze.ByteString.Builder
20+import Blaze.ByteString.Builder (Builder, fromByteString, toLazyByteString)
21−import Blaze.ByteString.Builder.Char.Utf8
21+import Blaze.Text (double, integral)
22−import Data.Attoparsec.Number (Number(..))
23import Data.Aeson.Types (ToJSON(..), Value(..))
22import Data.Aeson.Types (ToJSON(..), Value(..))
23+import Data.Attoparsec.Number (Number(..))
24import Data.Monoid (mappend)
24import Data.Monoid (mappend)
25+import Data.Text.Encoding (encodeUtf8)
25import Numeric (showHex)
26import Numeric (showHex)
26−import Blaze.Text (double, integral)
27+import qualified Blaze.ByteString.Builder.Char.Utf8 as Utf8
28+import qualified Blaze.ByteString.Builder.Char8 as Char8
27import qualified Data.ByteString.Lazy.Char8 as L
29import qualified Data.ByteString.Lazy.Char8 as L
28import qualified Data.HashMap.Strict as H
30import qualified Data.HashMap.Strict as H
29import qualified Data.Text as T
31import qualified Data.Text as T
@@ -31,27 +33,29 @@ import qualified Data.Vector as V
31
33
32-- | Encode a JSON value to a 'Builder'.
34-- | Encode a JSON value to a 'Builder'.
33fromValue :: Value -> Builder
35fromValue :: Value -> Builder
34−fromValue Null = fromByteString "null"
36+fromValue Null = {-# SCC "fromValue/Null" #-} fromByteString "null"
35−fromValue (Bool b) = fromByteString $ if b then "true" else "false"
37+fromValue (Bool b) = {-# SCC "fromValue/Bool" #-}
38+ if b then fromByteString "true"
39+ else fromByteString "false"
36−fromValue (Number n) = fromNumber n
40+fromValue (Number n) = {-# SCC "fromValue/Number" #-} fromNumber n
37−fromValue (String s) = string s
41+fromValue (String s) = {-# SCC "fromValue/String" #-} string s
38fromValue (Array v)
42fromValue (Array v)
39− | V.null v = fromByteString "[]"
43+ | V.null v = {-# SCC "fromValue/Array" #-} fromByteString "[]"
44+ | otherwise = {-# SCC "fromValue/Array" #-}
40− | otherwise = fromChar '[' `mappend`
45+ Char8.fromChar '[' `mappend`
41 fromValue (V.unsafeHead v) `mappend`
46 fromValue (V.unsafeHead v) `mappend`
42− V.foldr f (fromChar ']') (V.unsafeTail v)
47+ V.foldr f (Char8.fromChar ']') (V.unsafeTail v)
43− where f a z = fromChar ',' `mappend` fromValue a `mappend` z
48+ where f a z = Char8.fromChar ',' `mappend` fromValue a `mappend` z
44−fromValue (Object m) =
49+fromValue (Object m) = {-# SCC "fromValue/Object" #-}
45 case H.toList m of
50 case H.toList m of
46− (x:xs) -> fromChar '{' `mappend`
51+ (x:xs) -> Char8.fromChar '{' `mappend`
47− one x `mappend`
48− foldr f (fromChar '}') xs
52+ one x `mappend` foldr f (Char8.fromChar '}') xs
49− _ -> fromByteString "{}"
53+ _ -> fromByteString "{}"
50− where f a z = fromChar ',' `mappend` one a `mappend` z
54+ where f a z = Char8.fromChar ',' `mappend` one a `mappend` z
51− one (k,v) = string k `mappend` fromChar ':' `mappend` fromValue v
55+ one (k,v) = string k `mappend` Char8.fromChar ':' `mappend` fromValue v
52
56
53string :: T.Text -> Builder
57string :: T.Text -> Builder
54−string s = fromChar '"' `mappend` quote s `mappend` fromChar '"'
58+string s = Char8.fromChar '"' `mappend` (quote s) `mappend` Char8.fromChar '"'
55 where
59 where
56 quote q = case T.uncons t of
60 quote q = case T.uncons t of
57 Just (c,t') -> fromText h `mappend` escape c `mappend` quote t'
61 Just (c,t') -> fromText h `mappend` escape c `mappend` quote t'
@@ -64,10 +68,15 @@ string s = fromChar '"' `mappend` quote s `mappend` fromChar '"'
64 escape '\r' = fromByteString "\\r"
68 escape '\r' = fromByteString "\\r"
65 escape '\t' = fromByteString "\\t"
69 escape '\t' = fromByteString "\\t"
66 escape c
70 escape c
71+ | c < '\x20' = Char8.fromString $
67− | c < '\x20' = fromString $ "\\u" ++ replicate (4 - length h) '0' ++ h
72+ "\\u" ++ replicate (4 - length h) '0' ++ h
68− | otherwise = fromChar c
73+ | otherwise = Utf8.fromChar c
69 where h = showHex (fromEnum c) ""
74 where h = showHex (fromEnum c) ""
70
75
76+-- The version in blaze-builder is way slower.
77+fromText :: T.Text -> Builder
78+fromText t = fromByteString (encodeUtf8 t)
79+
71fromNumber :: Number -> Builder
80fromNumber :: Number -> Builder
72fromNumber (I i) = integral i
81fromNumber (I i) = integral i
73fromNumber (D d)
82fromNumber (D d)
@@ -76,5 +85,6 @@ fromNumber (D d)
76
85
77-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
86-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
78encode :: ToJSON a => a -> L.ByteString
87encode :: ToJSON a => a -> L.ByteString
79−encode = toLazyByteString . fromValue . toJSON
88+encode = {-# SCC "encode" #-} toLazyByteString . fromValue .
89+ {-# SCC "toJSON" #-} toJSON
80{-# INLINE encode #-}
90{-# INLINE encode #-}