@@ -0,0 +1,144 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+
3+#undef FUSION_CHECK
4+#ifdef FUSION_CHECK
5+{-# OPTIONS_GHC -ddump-simpl -ddump-to-file -dsuppress-all #-}
6+#endif
7+
8+-- |
9+-- Module : Streamly.Benchmark.Data.Serialize
10+-- Copyright : (c) 2023 Composewell
11+-- License : BSD-3-Clause
12+-- Maintainer : streamly@composewell.com
13+
14+module Main (main) where
15+
16+-------------------------------------------------------------------------------
17+-- Imports
18+-------------------------------------------------------------------------------
19+
20+import Control.DeepSeq (NFData(..))
21+import Control.Exception (assert)
22+import Control.Monad (replicateM_)
23+import GHC.Generics (Generic)
24+import System.Random (randomRIO)
25+
26+import Streamly.Internal.Data.Unbox (newBytes)
27+import Streamly.Internal.Data.Serialize
28+#define USE_TH
29+#ifdef USE_TH
30+import Streamly.Internal.Data.Serialize.TH
31+#endif
32+
33+import Gauge
34+import Streamly.Benchmark.Common
35+
36+-------------------------------------------------------------------------------
37+-- Types
38+-------------------------------------------------------------------------------
39+
40+data CustomDT1
41+ = CDT1C1
42+ | CDT1C2 Int
43+ | CDT1C3 Int Bool
44+ deriving (Generic, Show, Eq)
45+
46+#ifndef USE_TH
47+instance Serialize CustomDT1
48+#else
49+$(deriveSerialize ''CustomDT1)
50+#endif
51+
52+-------------------------------------------------------------------------------
53+-- Helpers
54+-------------------------------------------------------------------------------
55+
56+{-# INLINE pokeTimes #-}
57+pokeTimes :: forall a. Serialize a => a -> Int -> IO ()
58+pokeTimes val times = do
59+ let n =
60+ case size :: Size a of
61+ ConstSize x -> x
62+ VarSize f -> f val
63+ arr <- newBytes n
64+ replicateM_ times $ do
65+ serialize 0 arr val
66+
67+{-# INLINE peekTimes #-}
68+peekTimes :: forall a. Serialize a => a -> Int -> IO ()
69+peekTimes val times = do
70+ let n =
71+ case size :: Size a of
72+ ConstSize x -> x
73+ VarSize f -> f val
74+ arr <- newBytes n
75+ _ <- serialize 0 arr val
76+ replicateM_ times $ do
77+ (_, _ :: a) <- deserialize 0 arr
78+ return ()
79+
80+{-# INLINE roundtrip #-}
81+roundtrip :: forall a. (Eq a, Serialize a) => a -> Int -> IO ()
82+roundtrip val times = do
83+ let n =
84+ case size :: Size a of
85+ ConstSize x -> x
86+ VarSize f -> f val
87+ arr <- newBytes n
88+ replicateM_ times $ do
89+ _ <- serialize 0 arr val
90+ (_, val1) <- deserialize 0 arr
91+ assert (val == val1) (pure ())
92+
93+benchSink :: NFData b => String -> Int -> (Int -> IO b) -> Benchmark
94+benchSink name times f = bench name (nfIO (randomRIO (times, times) >>= f))
95+
96+-------------------------------------------------------------------------------
97+-- Benchmarks
98+-------------------------------------------------------------------------------
99+
100+allBenchmarks :: Int -> [Benchmark]
101+allBenchmarks times =
102+ [ bgroup "poke"
103+ [ benchSink "C1" times
104+ (pokeTimes (CDT1C1 :: CustomDT1))
105+ , benchSink "C2" times
106+ (pokeTimes ((CDT1C2 (5 :: Int)) :: CustomDT1))
107+ , benchSink "C3" times
108+ (pokeTimes ((CDT1C3 (5 :: Int) True) :: CustomDT1))
109+ ]
110+ , bgroup "peek"
111+ [ benchSink "C1" times
112+ (peekTimes (CDT1C1 :: CustomDT1))
113+ , benchSink "C2" times
114+ (peekTimes ((CDT1C2 (5 :: Int)) :: CustomDT1))
115+ , benchSink "C3" times
116+ (peekTimes ((CDT1C3 (5 :: Int) True) :: CustomDT1))
117+ ]
118+ , bgroup "roundtrip"
119+ [ benchSink "C1" times
120+ (roundtrip (CDT1C1 :: CustomDT1))
121+ , benchSink "C2" times
122+ (roundtrip ((CDT1C2 (5 :: Int)) :: CustomDT1))
123+ , benchSink "C3" times
124+ (roundtrip ((CDT1C3 (5 :: Int) True) :: CustomDT1))
125+ ]
126+ ]
127+
128+-------------------------------------------------------------------------------
129+-- Driver
130+-------------------------------------------------------------------------------
131+
132+main :: IO ()
133+main = do
134+#ifndef FUSION_CHECK
135+ runWithCLIOpts defaultStreamSize allBenchmarks
136+#else
137+ -- Enable FUSION_CHECK macro at the beginning of the file
138+ -- Enable one benchmark below, and run the benchmark
139+ -- Check the .dump-simpl output
140+ let value = 100000
141+ -- peekTimes ((CDT1C2 (5 :: Int)) :: CustomDT1) value
142+ roundtrip ((CDT1C2 (5 :: Int)) :: CustomDT1) value
143+ return ()
144+#endif