avro-0.6.2.1: bench/Bench/Encoding.hs
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE NumDecimals #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
module Bench.Encoding
where
import Control.DeepSeq
import Data.Avro (decodeContainerWithEmbeddedSchema, encodeValueWithSchema, nullCodec)
import qualified Data.Avro as Avro
import Data.Avro.Deriving (deriveAvroFromByteString, r)
import qualified Data.ByteString.Lazy as BL
import Data.List (unfoldr)
import qualified Data.Vector as Vector
import qualified System.Random as Random
-- import Gauge
import Criterion.Main
deriveAvroFromByteString [r|
{
"type": "record",
"name": "Outer",
"fields": [
{ "name": "name", "type": "string" },
{ "name": "inner", "type": {
"type": "record",
"name": "Inner",
"fields": [
{ "name": "id", "type": "int" }
]
}
},
{ "name": "other", "type": "Inner" }
]
}
|]
deriving instance NFData Inner
deriving instance NFData Outer
newOuter :: IO Outer
newOuter = do
i1 <- Random.randomRIO (minBound, maxBound)
i2 <- Random.randomRIO (minBound, maxBound)
pure $ Outer "Written" (Inner i1) (Inner i2)
many :: Int -> IO a -> IO (Vector.Vector a)
many = Vector.replicateM
encodeToBS :: Benchmark
encodeToBS = env (many 1e5 newOuter) $ \ values ->
bgroup "Encode to ByteString"
[ bgroup "Simple type"
[ bench "Encode via ToAvro" $ nf (fmap (BL.toStrict . encodeValueWithSchema schema'Outer)) values
]
]
encodeContainer :: Benchmark
encodeContainer = env (chunksOf 100 . Vector.toList <$> many 1e5 newOuter) $ \values ->
bgroup "Encode container"
[ bench "Via ToAvro" $ nfIO $ Avro.encodeContainerWithSchema nullCodec schema'Outer values
]
roundtripContainer :: Benchmark
roundtripContainer = env (chunksOf 100 . Vector.toList <$> many 1e5 newOuter) $ \values ->
bgroup "Roundtrip container"
[ bench "Via ToAvro/FromAvro" $ nfIO $ decodeContainerWithEmbeddedSchema @Outer <$> Avro.encodeContainerWithSchema nullCodec schema'Outer values
, bench "Via ToAvro/FromAvro/HasAvroSchema" $ nfIO $ decodeContainerWithEmbeddedSchema @Outer <$> Avro.encodeContainer nullCodec values
]
chunksOf :: Int -> [a] -> [[a]]
chunksOf n = takeWhile (not.null) . unfoldr (Just . splitAt n)