on main help sign in
Improve benchmarks. (#61)

* Use Criterion.env in benchmarks. Introduce NFData instance for each of the structures. It introduces additional dependency on the `deepseq`, but that is ok, as the library comes with GHC. starting * Introduce benchmark for insert function. Introduce benchmark for the insert function. Basically we are interested in two cases: 1. insert in an empty or very small map 2. insert in a big map Because complexity of the import does depend on the size of the map it may be easier to track that. * Restructure benchmarks to keep track of groups. Group benchmarks by the similar action, not by the implementation. * Add update benchmarks and fix insert. * Address review comments. * Prettify benchmarks. Rename Hack to DMapNF. Rename Common to Spec. Add documentation. * Update typerep-map.cabal * Correct mistakes.

commit35cb9718f96cde66d0b6620ab8e79560334566b0 authorAlexander Vershilov <alexander.vershilov@gmail.com> dateFri 19 Oct 2018, 04:53 (8 years ago) parent2114c0f
10 files changed+224−87
benchmark/CMap.hs+34−21 benchmark/CacheMap.hs+35−12 benchmark/DMap.hs+36−17 benchmark/Main.hs+34−18 benchmark/OptimalVector.hs+16−19 benchmark/Spec.hs+53 src/Data/TypeRepMap/Internal.hs+4 typerep-extra-impls/Data/TypeRep/CMap.hs+4 typerep-extra-impls/Data/TypeRep/OptimalVector.hs+4 typerep-map.cabal+4
benchmark/CMap.hs+34−21
@@ -9,29 +9,38 @@
99{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
1010
1111module CMap
12− ( benchMap
13− , prepareBenchMap
12+ ( spec
1413 ) where
1514
16−import Criterion.Main (Benchmark, bench, bgroup, nf)
15+import Criterion.Main (bench, nf, env, whnf)
1716
1817import Prelude hiding (lookup)
1918
20−import Control.DeepSeq (rnf)
21−import Control.Exception
19+import Spec
2220import Data.Maybe (fromJust)
2321import Data.Proxy (Proxy (..))
2422import Data.Typeable (Typeable)
2523import GHC.TypeLits
2624
27−import Data.TypeRep.CMap (TypeRepMap (..), empty, insert, keys, lookup)
25+import Data.TypeRep.CMap (TypeRepMap (..), empty, insert, lookup)
2826
29−benchMap :: Benchmark
30−benchMap = bgroup "map"
31− [ bench "lookup" $ nf tenLookups bigMap
32− --, bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)
33− --, bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)
34− ]
27+spec :: BenchSpec
28+spec = BenchSpec
29+ { benchLookup = Just $ \name ->
30+ env (mkMap 10000) $ \ ~bigMap ->
31+ bench name $ nf tenLookups bigMap
32+ , benchInsertSmall = Just $ \name ->
33+ bench name $ whnf (inserts empty 10) (Proxy @ 99999)
34+ , benchInsertBig = Just $ \name ->
35+ env (mkMap 10000) $ \ ~(bigMap) ->
36+ bench name $ whnf (inserts bigMap 1) (Proxy @ 99999)
37+ , benchUpdateSmall = Just $ \name ->
38+ env (mkMap 10) $ \ ~(smallMap) ->
39+ bench name $ whnf (inserts smallMap 10) (Proxy @ 0)
40+ , benchUpdateBig = Just $ \name ->
41+ env (mkMap 10000) $ \ ~(bigMap) ->
42+ bench name $ whnf (inserts bigMap 10) (Proxy @ 0)
43+ }
3544
3645tenLookups :: TypeRepMap (Proxy :: Nat -> *)
3746 -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40
@@ -42,16 +51,20 @@ tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)
4251 lp :: forall (a::Nat). Typeable a => Proxy a
4352 lp = fromJust $ lookup tmap
4453
45−-- TypeRepMap of 10000 elements
46−bigMap :: TypeRepMap (Proxy :: Nat -> *)
47−bigMap = buildBigMap 10000 (Proxy :: Proxy 0) empty
54+inserts :: forall a . (KnownNat a)
55+ => TypeRepMap (Proxy :: Nat -> *)
56+ -> Int
57+ -> Proxy (a :: Nat)
58+ -> TypeRepMap (Proxy :: Nat -> *)
59+inserts !c 0 _ = c
60+inserts !c n x = inserts
61+ (insert x c)
62+ (n-1)
63+ (Proxy :: Proxy (a+1))
64+
65+mkMap :: Int -> IO (TypeRepMap (Proxy :: Nat -> *))
66+mkMap n = pure $ buildBigMap n (Proxy :: Proxy 0) empty
4867
4968buildBigMap :: forall a . (KnownNat a) => Int -> Proxy (a :: Nat) -> TypeRepMap (Proxy :: Nat -> *) -> TypeRepMap (Proxy :: Nat -> *)
5069buildBigMap 1 x = insert x
5170buildBigMap n x = insert x . buildBigMap (n - 1) (Proxy :: Proxy (a + 1))
52−
53−rknf :: TypeRepMap f -> ()
54−rknf = rnf . keys
55−
56−prepareBenchMap :: IO ()
57−prepareBenchMap = evaluate (rknf bigMap)
benchmark/CacheMap.hs+35−12
@@ -9,10 +9,11 @@
99{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
1010
1111module CacheMap
12− ( benchCacheMap
12+ ( spec
1313 ) where
1414
15−import Criterion.Main (Benchmark, bench, bgroup, nf)
15+import Criterion.Main (bench, nf, whnf, env)
16+import Spec
1617
1718import Prelude hiding (lookup)
1819
@@ -22,14 +23,25 @@ import Data.Typeable (Typeable)
2223import GHC.Exts (fromList)
2324import GHC.TypeLits
2425
25−import Data.TypeRepMap.Internal (TypeRepMap (..), WrapTypeable (..), lookup)
26+import Data.TypeRepMap.Internal (TypeRepMap (..), WrapTypeable (..), lookup, insert, empty)
2627
27−benchCacheMap :: Benchmark
28−benchCacheMap = bgroup "vector optimal cache"
29− [ bench "lookup" $ nf tenLookups bigMap
30− -- , bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)
31− -- , bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)
32− ]
28+spec :: BenchSpec
29+spec = BenchSpec
30+ { benchLookup = Just $ \name ->
31+ env (mkMap 10000) $ \ ~bigMap ->
32+ bench name $ nf tenLookups bigMap
33+ , benchInsertSmall = Just $ \name ->
34+ bench name $ whnf (inserts empty 10) (Proxy @ 99999)
35+ , benchInsertBig = Just $ \name ->
36+ env (mkMap 10000) $ \ ~(bigMap) ->
37+ bench name $ whnf (inserts bigMap 1) (Proxy @ 99999)
38+ , benchUpdateSmall = Just $ \name ->
39+ env (mkMap 10) $ \ ~(smallMap) ->
40+ bench name $ whnf (inserts smallMap 10) (Proxy @ 0)
41+ , benchUpdateBig = Just $ \name ->
42+ env (mkMap 10000) $ \ ~(bigMap) ->
43+ bench name $ whnf (inserts bigMap 10) (Proxy @ 0)
44+ }
3345
3446tenLookups :: TypeRepMap (Proxy :: Nat -> *)
3547 -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40
@@ -40,9 +52,20 @@ tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)
4052 lp :: forall (a::Nat). Typeable a => Proxy a
4153 lp = fromJust $ lookup tmap
4254
43−-- TypeRepMap of 10000 elements
44−bigMap :: TypeRepMap (Proxy :: Nat -> *)
45−bigMap = fromList $ buildBigMap 10000 (Proxy :: Proxy 0) []
55+inserts :: forall a . (KnownNat a)
56+ => TypeRepMap (Proxy :: Nat -> *)
57+ -> Int
58+ -> Proxy (a :: Nat)
59+ -> TypeRepMap (Proxy :: Nat -> *)
60+inserts !c 0 _ = c
61+inserts !c n x = inserts
62+ (insert x c)
63+ (n-1)
64+ (Proxy :: Proxy (a+1))
65+
66+mkMap :: Int -> IO (TypeRepMap (Proxy :: Nat -> *))
67+mkMap n = pure $ fromList $ buildBigMap n (Proxy :: Proxy 0) []
68+
4669
4770buildBigMap :: forall a . (KnownNat a)
4871 => Int
benchmark/DMap.hs+36−17
@@ -11,16 +11,15 @@
1111{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver -fno-warn-orphans #-}
1212
1313module DMap
14− ( benchDMap
15− , prepareBenchDMap
14+ ( spec
1615 ) where
1716
18−import Criterion.Main (Benchmark, bench, bgroup, nf)
17+import Criterion.Main (bench, nf, whnf, env)
1918
2019import Prelude hiding (lookup)
2120
22−import Control.DeepSeq (rnf)
23−import Control.Exception
21+import Spec
22+import Control.DeepSeq (NFData(..))
2423import Data.Maybe (fromJust)
2524import Data.Proxy (Proxy (..))
2625import Data.Type.Equality ((:~:) (..))
@@ -35,12 +34,20 @@ import Data.Some (Some (This))
3534
3635type TypeRepMap = DMap TypeRep
3736
38−benchDMap :: Benchmark
39−benchDMap = bgroup "dependent map"
40− [ bench "lookup" $ nf tenLookups bigMap
41− -- , bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)
42− -- , bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)
43− ]
37+
38+spec :: BenchSpec
39+spec = BenchSpec
40+ { benchLookup = Just $ \name ->
41+ env mkBigMap $ \ ~(DMapNF bigMap) ->
42+ bench name $ nf tenLookups bigMap
43+ , benchInsertSmall = Just $ \name ->
44+ bench name $ whnf (inserts empty 10) (Proxy @ 99999)
45+ , benchInsertBig = Just $ \name ->
46+ env mkBigMap $ \ ~(DMapNF bigMap) ->
47+ bench name $ whnf (inserts bigMap 1) (Proxy @ 99999)
48+ , benchUpdateSmall = Nothing -- Not implemented
49+ , benchUpdateBig = Nothing -- Not implemented
50+ }
4451
4552tenLookups :: TypeRepMap (Proxy :: Nat -> *)
4653 -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40
@@ -51,9 +58,20 @@ tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)
5158 lp :: forall (a :: Nat) . Typeable a => Proxy a
5259 lp = fromJust $ lookup (typeRep @a) tmap
5360
61+inserts :: forall a . (KnownNat a)
62+ => TypeRepMap (Proxy :: Nat -> *)
63+ -> Int
64+ -> Proxy (a :: Nat)
65+ -> TypeRepMap (Proxy :: Nat -> *)
66+inserts !c 0 _ = c
67+inserts !c n x = inserts
68+ (insert (typeRep @ a) x c)
69+ (n-1)
70+ (Proxy :: Proxy (a+1))
71+
5472-- TypeRepMap of 10000 elements
55−bigMap :: TypeRepMap (Proxy :: Nat -> *)
56−bigMap = buildBigMap 10000 (Proxy :: Proxy 0) empty
73+mkBigMap :: IO (DMapNF (Proxy :: Nat -> *))
74+mkBigMap = pure . DMapNF $ buildBigMap 10000 (Proxy :: Proxy 0) empty
5775
5876buildBigMap :: forall a . (KnownNat a)
5977 => Int
@@ -64,11 +82,12 @@ buildBigMap 1 x = insert (typeRep @a) x
6482buildBigMap n x = insert (typeRep @a) x
6583 . buildBigMap (n - 1) (Proxy @(a + 1))
6684
67−rknf :: TypeRepMap f -> ()
68−rknf = rnf . map (\(This t) -> typeRepFingerprint t) . keys
85+-- | Wrapper that provides NFData instance to the 'DMap' structure.
86+newtype DMapNF f = DMapNF (TypeRepMap f)
6987
70−prepareBenchDMap :: IO ()
71−prepareBenchDMap = evaluate (rknf bigMap)
88+instance NFData (DMapNF f) where
89+ rnf (DMapNF x) =
90+ rnf . map (\(This t) -> typeRepFingerprint t) $ keys x
7291
7392instance GEq TypeRep where
7493 geq :: TypeRep a -> TypeRep b -> Maybe (a :~: b)
benchmark/Main.hs+34−18
@@ -2,30 +2,46 @@
22
33module Main where
44
5−import Criterion.Main (defaultMain)
5+import Criterion.Main (defaultMain, bgroup)
66
7−import CacheMap (benchCacheMap)
8−import CMap (benchMap, prepareBenchMap)
7+import Spec
8+import qualified CMap
9+import qualified CacheMap
910#if ( __GLASGOW_HASKELL__ >= 802 )
10−import DMap (benchDMap, prepareBenchDMap)
11+import qualified DMap
1112#endif
12−import OptimalVector (benchVectorOpt, prepareBenchVectorOpt)
13−--import Vector (benchVector, prepareBenchVector)
13+import qualified OptimalVector as OptVec
1414
1515main :: IO ()
1616main = do
17− prepareBenchMap
18− --prepareBenchVector
19− prepareBenchVectorOpt
17+ let specs = [("CMap", CMap.spec)
18+ ,("CacheMap", CacheMap.spec)
2019#if ( __GLASGOW_HASKELL__ >= 802 )
21− prepareBenchDMap
20+ , ("DMap", DMap.spec)
2221#endif
22+ , ("OptVec", OptVec.spec)
23+ ]
24+ -- This code creates a benchmark group. Given a getter
25+ -- (that is test description) it gets a benchmark generation
26+ -- function from each module spec. Benchmark generation
27+ -- function takes a label and generate benchmarks. It's
28+ -- possible to introduce parameters passing in the same way.
29+ mkGroup getBenchmark =
30+ [ mkBenchmark label
31+ | (label, spec) <- specs
32+ -- Here we use pure to force pattern matching in List
33+ -- then in case of pattern match failure `mzero` will
34+ -- be called, so benchmark will be ignored.
35+ , Just mkBenchmark <- pure $ getBenchmark spec
36+ ]
2337 defaultMain
24− [ benchMap
25− -- , benchVector
26− , benchCacheMap
27− , benchVectorOpt
28−#if ( __GLASGOW_HASKELL__ >= 802 )
29− , benchDMap
30−#endif
31− ]
38+ [ bgroup "lookup" $ mkGroup benchLookup
39+ , bgroup "insert"
40+ [ bgroup "10 elements to empty" $ mkGroup benchInsertSmall
41+ , bgroup "1 element to big map" $ mkGroup benchInsertBig
42+ ]
43+ , bgroup "update"
44+ [ bgroup "10 elements to empty" $ mkGroup benchUpdateSmall
45+ , bgroup "1 element to big map" $ mkGroup benchUpdateBig
46+ ]
47+ ]
benchmark/OptimalVector.hs+16−19
@@ -10,16 +10,14 @@
1010{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
1111
1212module OptimalVector
13− ( benchVectorOpt
14− , prepareBenchVectorOpt
13+ ( spec
1514 ) where
1615
17−import Criterion.Main (Benchmark, bench, bgroup, nf)
16+import Spec
17+import Criterion.Main (bench, nf, env)
1818
1919import Prelude hiding (lookup)
2020
21−import Control.DeepSeq (rnf)
22−import Control.Exception
2321import Data.Maybe (fromJust)
2422import Data.Proxy (Proxy (..))
2523import Data.Typeable (Typeable)
@@ -27,13 +25,17 @@ import GHC.TypeLits
2725
2826import Data.TypeRep.OptimalVector (TF (..), TypeRepMap (..), fromList, lookup)
2927
30−benchVectorOpt :: Benchmark
31−benchVectorOpt = bgroup "vector optimal"
32− [ bench "lookup" $ nf tenLookups bigMap
33− -- , bench "insert new" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 9999999999)
34− -- , bench "update old" $ whnf (\x -> rknf $ insert x bigMap) (Proxy :: Proxy 1)
35− ]
36−
28+spec :: BenchSpec
29+spec = BenchSpec
30+ { benchLookup = Just $ \name ->
31+ env mkBigMap $ \ ~bigMap ->
32+ bench name $ nf tenLookups bigMap
33+ , benchInsertSmall = Nothing -- Not implemented
34+ , benchInsertBig = Nothing -- Not implemented
35+ , benchUpdateSmall = Nothing -- Not implemented
36+ , benchUpdateBig = Nothing -- Not implemented
37+ }
38+
3739tenLookups :: TypeRepMap (Proxy :: Nat -> *)
3840 -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40
3941 , Proxy 50, Proxy 60, Proxy 70, Proxy 80
@@ -44,8 +46,8 @@ tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)
4446 lp = fromJust $ lookup tmap
4547
4648-- TypeRepMap of 10000 elements
47−bigMap :: TypeRepMap (Proxy :: Nat -> *)
48−bigMap = fromList $ buildBigMap 10000 (Proxy :: Proxy 0) []
49+mkBigMap :: IO (TypeRepMap (Proxy :: Nat -> *))
50+mkBigMap = pure $ fromList $ buildBigMap 10000 (Proxy :: Proxy 0) []
4951
5052buildBigMap :: forall a . (KnownNat a)
5153 => Int
@@ -55,8 +57,3 @@ buildBigMap :: forall a . (KnownNat a)
5557buildBigMap 1 x = (TF x :)
5658buildBigMap n x = (TF x :) . buildBigMap (n - 1) (Proxy :: Proxy (a + 1))
5759
58−rknf :: TypeRepMap f -> ()
59−rknf tVect = rnf (fingerprintAs tVect, fingerprintBs tVect)
60−
61−prepareBenchVectorOpt :: IO ()
62−prepareBenchVectorOpt = evaluate (rknf bigMap)
benchmark/Spec.hsnew file+53
@@ -0,0 +1,53 @@
1+-- | Specification of the benchmarks.
2+-- This module keeps a list of all bencharks, this way
3+-- we can group benchmark by the interesting function, not
4+-- by the implementation.
5+module Spec
6+ ( BenchSpec(..)
7+ ) where
8+
9+import Criterion
10+
11+-- | List of benchmarks that each module should provide.
12+-- If implementation can express the benchmark then it
13+-- can return @Nothing@ in that benchmark.
14+--
15+-- Map should contain elements from @1@ to @size of map@
16+-- inserted in ascending order (later that requirement may
17+-- change).
18+data BenchSpec = BenchSpec
19+ { benchLookup :: Maybe (String -> Benchmark)
20+ -- ^ Basic lookup we look 10 values inside 10k map.
21+ --
22+ -- Implementation may look like:
23+ -- @
24+ -- tenLookups :: TypeRepMap (Proxy :: Nat -> *)
25+ -- -> ( Proxy 10, Proxy 20, Proxy 30, Proxy 40
26+ -- , Proxy 50, Proxy 60, Proxy 70, Proxy 80
27+ -- )
28+ -- tenLookups tmap = (lp, lp, lp, lp, lp, lp, lp, lp)
29+ -- @
30+ , benchInsertSmall :: Maybe (String -> Benchmark)
31+ -- ^ Insert 10 elements into an empty map.
32+ --
33+ -- Implementation may look like:
34+ -- @
35+ -- inserts :: forall a . (KnownNat a)
36+ -- => TypeRepMap (Proxy :: Nat -> *)
37+ -- -> Int
38+ -- -> Proxy (a :: Nat)
39+ -- -> TypeRepMap (Proxy :: Nat -> *)
40+ -- inserts !c 0 _ = c
41+ -- inserts !c n x = inserts (insert x c) (n-1) (Proxy :: Proxy (a+1))
42+ -- @
43+ , benchInsertBig :: Maybe (String -> Benchmark)
44+ -- ^ Insert 10 elements into a big map. Implementation is like
45+ -- a small map, but should insert values into 10k elements map.
46+ , benchUpdateSmall :: Maybe (String -> Benchmark)
47+ -- ^ Insert 10 elements into map of 10 elements, where each key
48+ -- was already inserted in the map
49+ , benchUpdateBig :: Maybe (String -> Benchmark)
50+ -- ^ Insert 10 elements into map of 10k elements, where each key
51+ -- was already inserted in the map
52+ }
53+
src/Data/TypeRepMap/Internal.hs+4
@@ -25,6 +25,7 @@ import Prelude hiding (lookup)
2525
2626import Control.Monad.ST (ST, runST)
2727import Control.Monad.Zip (mzip)
28+import Control.DeepSeq
2829import Data.Function (on)
2930import Data.Kind (Type)
3031import Data.List (intercalate, nubBy)
@@ -74,6 +75,9 @@ data TypeRepMap (f :: k -> Type) =
7475 }
7576 -- ^ an unsafe constructor for 'TypeRepMap'
7677
78+instance NFData (TypeRepMap f) where
79+ rnf x = rnf (keys x) `seq` ()
80+
7781-- | Shows only keys.
7882instance Show (TypeRepMap f) where
7983 show TypeRepMap{..} = "TypeRepMap [" ++ showKeys ++ "]"
typerep-extra-impls/Data/TypeRep/CMap.hs+4
@@ -12,6 +12,7 @@ module Data.TypeRep.CMap
1212
1313import Prelude hiding (lookup)
1414
15+import Control.DeepSeq
1516import Data.Proxy (Proxy (..))
1617import Data.Typeable (TypeRep, Typeable, typeRep)
1718import GHC.Base (Any)
@@ -24,6 +25,9 @@ newtype TypeRepMap (f :: k -> *) = TypeRepMap
2425 { unMap :: LMap.Map TypeRep Any
2526 }
2627
28+instance NFData (TypeRepMap f) where
29+ rnf x = rnf (keys x) `seq` ()
30+
2731-- | Empty structure.
2832empty :: TypeRepMap f
2933empty = TypeRepMap mempty
typerep-extra-impls/Data/TypeRep/OptimalVector.hs+4
@@ -23,6 +23,7 @@ module Data.TypeRep.OptimalVector
2323import Prelude hiding (lookup)
2424
2525import Control.Arrow ((&&&))
26+import Control.DeepSeq
2627import Data.Kind (Type)
2728import Data.Proxy (Proxy (..))
2829import Data.Typeable (Typeable, typeRep, typeRepFingerprint)
@@ -41,6 +42,9 @@ data TypeRepMap (f :: k -> Type) = TypeRepMap
4142 , anys :: V.Vector Any
4243 }
4344
45+instance NFData (TypeRepMap f) where
46+ rnf x = x `seq` ()
47+
4448fromAny :: Any -> f a
4549fromAny = unsafeCoerce
4650
typerep-map.cabal+4
@@ -45,6 +45,7 @@ library
4545 , containers >= 0.5.10.2 && < 0.7
4646 , ghc-prim ^>= 0.5.1.1
4747 , primitive ^>= 0.6.4
48+ , deepseq ^>= 1.4
4849 default-extensions: OverloadedStrings
4950 RecordWildCards
5051 ScopedTypeVariables
@@ -60,6 +61,7 @@ library typerep-extra-impls
6061 build-depends: base >= 4.10 && < 5
6162 , containers >= 0.5.10.2 && < 0.7
6263 , vector ^>= 0.12.0.1
64+ , deepseq ^>= 1.4
6365 default-extensions: OverloadedStrings
6466 RecordWildCards
6567 ScopedTypeVariables
@@ -101,6 +103,7 @@ benchmark typerep-map-benchmark
101103 main-is: Main.hs
102104 other-modules: CMap
103105 , CacheMap
106+ , Spec
104107 , Vector
105108 , OptimalVector
106109 build-depends: base >= 4.10 && < 5
@@ -115,5 +118,6 @@ benchmark typerep-map-benchmark
115118 RecordWildCards
116119 ScopedTypeVariables
117120 TypeApplications
121+ BangPatterns
118122 if impl(ghc >= 8.2.2)
119123 other-modules: DMap