dhodovsk / source-git / ghc-aeson

Forked from source-git/ghc-aeson 4 years ago
Clone

Blame benchmarks/Compare/JsonBench.hs

Packit 9a2dfb
-- Adapted from a buffer-builder benchmark:
Packit 9a2dfb
--
Packit 9a2dfb
-- https://github.com/chadaustin/buffer-builder/blob/master/test.json
Packit 9a2dfb
Packit 9a2dfb
{-# LANGUAGE BangPatterns #-}
Packit 9a2dfb
{-# LANGUAGE MagicHash #-}
Packit 9a2dfb
{-# LANGUAGE OverloadedStrings #-}
Packit 9a2dfb
{-# LANGUAGE RecordWildCards #-}
Packit 9a2dfb
{-# LANGUAGE ScopedTypeVariables #-}
Packit 9a2dfb
Packit 9a2dfb
module Compare.JsonBench (benchmarks) where
Packit 9a2dfb
Packit 9a2dfb
import Prelude ()
Packit 9a2dfb
import Prelude.Compat
Packit 9a2dfb
Packit 9a2dfb
import Control.DeepSeq (NFData(..))
Packit 9a2dfb
import Criterion
Packit 9a2dfb
import Data.Aeson ((.:))
Packit 9a2dfb
import Data.Monoid ((<>))
Packit 9a2dfb
import Data.Text (Text)
Packit 9a2dfb
import Typed.Common (load)
Packit 9a2dfb
import qualified Data.Aeson as Aeson
Packit 9a2dfb
import qualified Data.BufferBuilder.Json as Json
Packit 9a2dfb
import qualified Data.Json.Builder as JB
Packit 9a2dfb
Packit 9a2dfb
data EyeColor = Green | Blue | Brown
Packit 9a2dfb
    deriving (Eq, Show)
Packit 9a2dfb
data Gender = Male | Female
Packit 9a2dfb
    deriving (Eq, Show)
Packit 9a2dfb
data Fruit = Apple | Strawberry | Banana
Packit 9a2dfb
    deriving (Eq, Show)
Packit 9a2dfb
data Friend = Friend
Packit 9a2dfb
    { fId :: !Int
Packit 9a2dfb
    , fName :: !Text
Packit 9a2dfb
    } deriving (Eq, Show)
Packit 9a2dfb
Packit 9a2dfb
data User = User
Packit 9a2dfb
    { uId       :: !Text
Packit 9a2dfb
    , uIndex    :: !Int
Packit 9a2dfb
    , uGuid     :: !Text
Packit 9a2dfb
    , uIsActive :: !Bool
Packit 9a2dfb
    , uBalance  :: !Text
Packit 9a2dfb
    , uPicture  :: !Text
Packit 9a2dfb
    , uAge      :: !Int
Packit 9a2dfb
    , uEyeColor :: !EyeColor
Packit 9a2dfb
    , uName     :: !Text
Packit 9a2dfb
    , uGender   :: !Gender
Packit 9a2dfb
    , uCompany  :: !Text
Packit 9a2dfb
    , uEmail    :: !Text
Packit 9a2dfb
    , uPhone    :: !Text
Packit 9a2dfb
    , uAddress  :: !Text
Packit 9a2dfb
    , uAbout    :: !Text
Packit 9a2dfb
    , uRegistered   :: !Text -- UTCTime?
Packit 9a2dfb
    , uLatitude :: !Double
Packit 9a2dfb
    , uLongitude    :: !Double
Packit 9a2dfb
    , uTags :: ![Text]
Packit 9a2dfb
    , uFriends  :: ![Friend]
Packit 9a2dfb
    , uGreeting :: !Text
Packit 9a2dfb
    , uFavouriteFruit   :: !Fruit
Packit 9a2dfb
    } deriving (Eq, Show)
Packit 9a2dfb
Packit 9a2dfb
instance NFData EyeColor where rnf !_ = ()
Packit 9a2dfb
instance NFData Gender where rnf !_ = ()
Packit 9a2dfb
instance NFData Fruit where rnf !_ = ()
Packit 9a2dfb
Packit 9a2dfb
instance NFData Friend where
Packit 9a2dfb
    rnf Friend {..} = rnf fId `seq` rnf fName `seq` ()
Packit 9a2dfb
Packit 9a2dfb
instance NFData User where
Packit 9a2dfb
    rnf User {..} = rnf uId `seq` rnf uIndex `seq` rnf uGuid `seq` rnf uIsActive `seq` rnf uBalance `seq` rnf uPicture `seq` rnf uAge `seq` rnf uEyeColor `seq` rnf uName `seq` rnf uGender `seq` rnf uCompany `seq` rnf uEmail `seq` rnf uPhone `seq` rnf uAddress `seq` rnf uAbout `seq` rnf uRegistered `seq` rnf uLatitude `seq` rnf uLongitude `seq` rnf uTags `seq` rnf uFriends `seq` rnf uGreeting `seq` rnf uFavouriteFruit `seq` ()
Packit 9a2dfb
Packit 9a2dfb
eyeColorTable :: [(Text, EyeColor)]
Packit 9a2dfb
eyeColorTable = [("brown", Brown), ("green", Green), ("blue", Blue)]
Packit 9a2dfb
Packit 9a2dfb
genderTable :: [(Text, Gender)]
Packit 9a2dfb
genderTable = [("male", Male), ("female", Female)]
Packit 9a2dfb
Packit 9a2dfb
fruitTable :: [(Text, Fruit)]
Packit 9a2dfb
fruitTable = [("apple", Apple), ("strawberry", Strawberry), ("banana", Banana)]
Packit 9a2dfb
Packit 9a2dfb
enumFromJson :: Monad m => String -> [(Text, enum)] -> (json -> m Text) -> json -> m enum
Packit 9a2dfb
enumFromJson enumName table extract v = do
Packit 9a2dfb
    s <- extract v
Packit 9a2dfb
    case lookup s table of
Packit 9a2dfb
        Just r -> return r
Packit 9a2dfb
        Nothing -> fail $ "Bad " ++ enumName ++ ": " ++ show s
Packit 9a2dfb
Packit 9a2dfb
--- Aeson instances ---
Packit 9a2dfb
Packit 9a2dfb
instance Aeson.FromJSON EyeColor where
Packit 9a2dfb
    parseJSON = enumFromJson "EyeColor" eyeColorTable Aeson.parseJSON
Packit 9a2dfb
Packit 9a2dfb
instance Aeson.FromJSON Gender where
Packit 9a2dfb
    parseJSON = enumFromJson "Gender" genderTable Aeson.parseJSON
Packit 9a2dfb
Packit 9a2dfb
instance Aeson.FromJSON Fruit where
Packit 9a2dfb
    parseJSON = enumFromJson "Fruit" fruitTable Aeson.parseJSON
Packit 9a2dfb
Packit 9a2dfb
instance Aeson.FromJSON Friend where
Packit 9a2dfb
    parseJSON = Aeson.withObject "Friend" $ \o -> do
Packit 9a2dfb
        fId <- o .: "id"
Packit 9a2dfb
        fName <- o .: "name"
Packit 9a2dfb
        return Friend {..}
Packit 9a2dfb
Packit 9a2dfb
instance Aeson.FromJSON User where
Packit 9a2dfb
    parseJSON = Aeson.withObject "User" $ \o -> do
Packit 9a2dfb
        uId <- o .: "_id"
Packit 9a2dfb
        uIndex <- o .: "index"
Packit 9a2dfb
        uGuid <- o .: "guid"
Packit 9a2dfb
        uIsActive <- o .: "isActive"
Packit 9a2dfb
        uBalance <- o .: "balance"
Packit 9a2dfb
        uPicture <- o .: "picture"
Packit 9a2dfb
        uAge <- o .: "age"
Packit 9a2dfb
        uEyeColor <- o .: "eyeColor"
Packit 9a2dfb
        uName <- o .: "name"
Packit 9a2dfb
        uGender <- o .: "gender"
Packit 9a2dfb
        uCompany <- o .: "company"
Packit 9a2dfb
        uEmail <- o .: "email"
Packit 9a2dfb
        uPhone <- o .: "phone"
Packit 9a2dfb
        uAddress <- o .: "address"
Packit 9a2dfb
        uAbout <- o .: "about"
Packit 9a2dfb
        uRegistered <- o .: "registered"
Packit 9a2dfb
        uLatitude <- o .: "latitude"
Packit 9a2dfb
        uLongitude <- o .: "longitude"
Packit 9a2dfb
        uTags <- o .: "tags"
Packit 9a2dfb
        uFriends <- o .: "friends"
Packit 9a2dfb
        uGreeting <- o .: "greeting"
Packit 9a2dfb
        uFavouriteFruit <- o .: "favoriteFruit"
Packit 9a2dfb
        return User {..}
Packit 9a2dfb
Packit 9a2dfb
instance Aeson.ToJSON EyeColor where
Packit 9a2dfb
    toJSON ec = Aeson.toJSON $ case ec of
Packit 9a2dfb
        Green -> "green" :: Text
Packit 9a2dfb
        Blue -> "blue"
Packit 9a2dfb
        Brown -> "brown"
Packit 9a2dfb
Packit 9a2dfb
    toEncoding ec = Aeson.toEncoding $ case ec of
Packit 9a2dfb
        Green -> "green" :: Text
Packit 9a2dfb
        Blue -> "blue"
Packit 9a2dfb
        Brown -> "brown"
Packit 9a2dfb
Packit 9a2dfb
instance Aeson.ToJSON Gender where
Packit 9a2dfb
    toJSON g = Aeson.toJSON $ case g of
Packit 9a2dfb
        Male -> "male" :: Text
Packit 9a2dfb
        Female -> "female"
Packit 9a2dfb
Packit 9a2dfb
    toEncoding g = Aeson.toEncoding $ case g of
Packit 9a2dfb
        Male -> "male" :: Text
Packit 9a2dfb
        Female -> "female"
Packit 9a2dfb
Packit 9a2dfb
instance Aeson.ToJSON Fruit where
Packit 9a2dfb
    toJSON f = Aeson.toJSON $ case f of
Packit 9a2dfb
        Apple -> "apple" :: Text
Packit 9a2dfb
        Banana -> "banana"
Packit 9a2dfb
        Strawberry -> "strawberry"
Packit 9a2dfb
Packit 9a2dfb
    toEncoding f = Aeson.toEncoding $ case f of
Packit 9a2dfb
        Apple -> "apple" :: Text
Packit 9a2dfb
        Banana -> "banana"
Packit 9a2dfb
        Strawberry -> "strawberry"
Packit 9a2dfb
Packit 9a2dfb
instance Aeson.ToJSON Friend where
Packit 9a2dfb
    toJSON Friend {..} = Aeson.object
Packit 9a2dfb
        [ "id" Aeson..= fId
Packit 9a2dfb
        , "name" Aeson..= fName
Packit 9a2dfb
        ]
Packit 9a2dfb
Packit 9a2dfb
    toEncoding Friend {..} = Aeson.pairs $
Packit 9a2dfb
           "id" Aeson..= fId
Packit 9a2dfb
        <> "name" Aeson..= fName
Packit 9a2dfb
Packit 9a2dfb
instance Aeson.ToJSON User where
Packit 9a2dfb
    toJSON User{..} = Aeson.object
Packit 9a2dfb
        [ "_id" Aeson..= uId
Packit 9a2dfb
        , "index" Aeson..= uIndex
Packit 9a2dfb
        , "guid" Aeson..= uGuid
Packit 9a2dfb
        , "isActive" Aeson..= uIsActive
Packit 9a2dfb
        , "balance" Aeson..= uBalance
Packit 9a2dfb
        , "picture" Aeson..= uPicture
Packit 9a2dfb
        , "age" Aeson..= uAge
Packit 9a2dfb
        , "eyeColor" Aeson..= uEyeColor
Packit 9a2dfb
        , "name" Aeson..= uName
Packit 9a2dfb
        , "gender" Aeson..= uGender
Packit 9a2dfb
        , "company" Aeson..= uCompany
Packit 9a2dfb
        , "email" Aeson..= uEmail
Packit 9a2dfb
        , "phone" Aeson..= uPhone
Packit 9a2dfb
        , "address" Aeson..= uAddress
Packit 9a2dfb
        , "about" Aeson..= uAbout
Packit 9a2dfb
        , "registered" Aeson..= uRegistered
Packit 9a2dfb
        , "latitude" Aeson..= uLatitude
Packit 9a2dfb
        , "longitude" Aeson..= uLongitude
Packit 9a2dfb
        , "tags" Aeson..= uTags
Packit 9a2dfb
        , "friends" Aeson..= uFriends
Packit 9a2dfb
        , "greeting" Aeson..= uGreeting
Packit 9a2dfb
        , "favoriteFruit" Aeson..= uFavouriteFruit
Packit 9a2dfb
        ]
Packit 9a2dfb
Packit 9a2dfb
    toEncoding User{..} = Aeson.pairs $
Packit 9a2dfb
          "_id" Aeson..= uId
Packit 9a2dfb
        <> "index" Aeson..= uIndex
Packit 9a2dfb
        <> "guid" Aeson..= uGuid
Packit 9a2dfb
        <> "isActive" Aeson..= uIsActive
Packit 9a2dfb
        <> "balance" Aeson..= uBalance
Packit 9a2dfb
        <> "picture" Aeson..= uPicture
Packit 9a2dfb
        <> "age" Aeson..= uAge
Packit 9a2dfb
        <> "eyeColor" Aeson..= uEyeColor
Packit 9a2dfb
        <> "name" Aeson..= uName
Packit 9a2dfb
        <> "gender" Aeson..= uGender
Packit 9a2dfb
        <> "company" Aeson..= uCompany
Packit 9a2dfb
        <> "email" Aeson..= uEmail
Packit 9a2dfb
        <> "phone" Aeson..= uPhone
Packit 9a2dfb
        <> "address" Aeson..= uAddress
Packit 9a2dfb
        <> "about" Aeson..= uAbout
Packit 9a2dfb
        <> "registered" Aeson..= uRegistered
Packit 9a2dfb
        <> "latitude" Aeson..= uLatitude
Packit 9a2dfb
        <> "longitude" Aeson..= uLongitude
Packit 9a2dfb
        <> "tags" Aeson..= uTags
Packit 9a2dfb
        <> "friends" Aeson..= uFriends
Packit 9a2dfb
        <> "greeting" Aeson..= uGreeting
Packit 9a2dfb
        <> "favoriteFruit" Aeson..= uFavouriteFruit
Packit 9a2dfb
Packit 9a2dfb
--- BufferBuilder instances ---
Packit 9a2dfb
Packit 9a2dfb
instance Json.ToJson EyeColor where
Packit 9a2dfb
    toJson ec = Json.toJson $ case ec of
Packit 9a2dfb
        Green -> "green" :: Text
Packit 9a2dfb
        Blue -> "blue"
Packit 9a2dfb
        Brown -> "brown"
Packit 9a2dfb
Packit 9a2dfb
instance Json.ToJson Gender where
Packit 9a2dfb
    toJson g = Json.toJson $ case g of
Packit 9a2dfb
        Male -> "male" :: Text
Packit 9a2dfb
        Female -> "female"
Packit 9a2dfb
Packit 9a2dfb
instance Json.ToJson Fruit where
Packit 9a2dfb
    toJson f = Json.toJson $ case f of
Packit 9a2dfb
        Apple -> "apple" :: Text
Packit 9a2dfb
        Strawberry -> "strawberry"
Packit 9a2dfb
        Banana -> "banana"
Packit 9a2dfb
Packit 9a2dfb
instance Json.ToJson Friend where
Packit 9a2dfb
    toJson Friend{..} = Json.toJson $
Packit 9a2dfb
            "_id" Json..= fId
Packit 9a2dfb
            <> "name" Json..= fName
Packit 9a2dfb
Packit 9a2dfb
instance Json.ToJson User where
Packit 9a2dfb
    toJson User{..} = Json.toJson $
Packit 9a2dfb
            "_id"# Json..=# uId
Packit 9a2dfb
            <> "index"# Json..=# uIndex
Packit 9a2dfb
            <> "guid"# Json..=# uGuid
Packit 9a2dfb
            <> "isActive"# Json..=# uIsActive
Packit 9a2dfb
            <> "balance"# Json..=# uBalance
Packit 9a2dfb
            <> "picture"# Json..=# uPicture
Packit 9a2dfb
            <> "age"# Json..=# uAge
Packit 9a2dfb
            <> "eyeColor"# Json..=# uEyeColor
Packit 9a2dfb
            <> "name"# Json..=# uName
Packit 9a2dfb
            <> "gender"# Json..=# uGender
Packit 9a2dfb
            <> "company"# Json..=# uCompany
Packit 9a2dfb
            <> "email"# Json..=# uEmail
Packit 9a2dfb
            <> "phone"# Json..=# uPhone
Packit 9a2dfb
            <> "address"# Json..=# uAddress
Packit 9a2dfb
            <> "about"# Json..=# uAbout
Packit 9a2dfb
            <> "registered"# Json..=# uRegistered
Packit 9a2dfb
            <> "latitude"# Json..=# uLatitude
Packit 9a2dfb
            <> "longitude"# Json..=# uLongitude
Packit 9a2dfb
            <> "tags"# Json..=# uTags
Packit 9a2dfb
            <> "friends"# Json..=# uFriends
Packit 9a2dfb
            <> "greeting"# Json..=# uGreeting
Packit 9a2dfb
            <> "favoriteFruit"# Json..=# uFavouriteFruit
Packit 9a2dfb
Packit 9a2dfb
---- json-builder instances ----
Packit 9a2dfb
Packit 9a2dfb
instance JB.Value EyeColor where
Packit 9a2dfb
    toJson ec = JB.toJson $ case ec of
Packit 9a2dfb
        Green -> "green" :: Text
Packit 9a2dfb
        Blue -> "blue"
Packit 9a2dfb
        Brown -> "brown"
Packit 9a2dfb
Packit 9a2dfb
instance JB.Value Gender where
Packit 9a2dfb
    toJson g = JB.toJson $ case g of
Packit 9a2dfb
        Male -> "male" :: Text
Packit 9a2dfb
        Female -> "female"
Packit 9a2dfb
Packit 9a2dfb
instance JB.Value Fruit where
Packit 9a2dfb
    toJson f = JB.toJson $ case f of
Packit 9a2dfb
        Apple -> "apple" :: Text
Packit 9a2dfb
        Strawberry -> "strawberry"
Packit 9a2dfb
        Banana -> "banana"
Packit 9a2dfb
Packit 9a2dfb
instance JB.Value Friend where
Packit 9a2dfb
    toJson Friend{..} = JB.toJson $
Packit 9a2dfb
            ("_id" :: Text) `JB.row` fId
Packit 9a2dfb
            <> ("name" :: Text) `JB.row` fName
Packit 9a2dfb
Packit 9a2dfb
instance JB.Value User where
Packit 9a2dfb
    toJson User{..} =
Packit 9a2dfb
        let t :: Text -> Text
Packit 9a2dfb
            t = id
Packit 9a2dfb
        in JB.toJson $
Packit 9a2dfb
               t "_id" `JB.row` uId
Packit 9a2dfb
            <> t "index" `JB.row` uIndex
Packit 9a2dfb
            <> t "guid" `JB.row` uGuid
Packit 9a2dfb
            <> t "isActive" `JB.row` uIsActive
Packit 9a2dfb
            <> t "balance" `JB.row` uBalance
Packit 9a2dfb
            <> t "picture" `JB.row` uPicture
Packit 9a2dfb
            <> t "age" `JB.row` uAge
Packit 9a2dfb
            <> t "eyeColor" `JB.row` uEyeColor
Packit 9a2dfb
            <> t "name" `JB.row` uName
Packit 9a2dfb
            <> t "gender" `JB.row` uGender
Packit 9a2dfb
            <> t "company" `JB.row` uCompany
Packit 9a2dfb
            <> t "email" `JB.row` uEmail
Packit 9a2dfb
            <> t "phone" `JB.row` uPhone
Packit 9a2dfb
            <> t "address" `JB.row` uAddress
Packit 9a2dfb
            <> t "about" `JB.row` uAbout
Packit 9a2dfb
            <> t "registered" `JB.row` uRegistered
Packit 9a2dfb
            <> t "latitude" `JB.row` uLatitude
Packit 9a2dfb
            <> t "longitude" `JB.row` uLongitude
Packit 9a2dfb
            <> t "tags" `JB.row` uTags
Packit 9a2dfb
            <> t "friends" `JB.row` uFriends
Packit 9a2dfb
            <> t "greeting" `JB.row` uGreeting
Packit 9a2dfb
            <> t "favoriteFruit" `JB.row` uFavouriteFruit
Packit 9a2dfb
Packit 9a2dfb
benchmarks :: Benchmark
Packit 9a2dfb
benchmarks = env (load "json-data/buffer-builder.json") $
Packit 9a2dfb
    \ ~(parsedUserList :: [User]) ->
Packit 9a2dfb
    bgroup "json-bench" [
Packit 9a2dfb
      bench "aeson" $ nf Aeson.encode parsedUserList
Packit 9a2dfb
    , bench "buffer-builder" $ nf Json.encodeJson parsedUserList
Packit 9a2dfb
    , bench "json-builder" $ nf JB.toJsonLBS parsedUserList
Packit 9a2dfb
    ]