@@ -12,15 +12,18 @@ module Inspect.Alloc where
1212
1313import Control.Monad.ST
1414import Data.Int
15+ import Data.Word
16+ import Data.Char
1517-- import Data.Monoid
1618import Data.Functor.Identity
19+ import Foreign.Storable (sizeOf )
1720import Test.Tasty
1821import Test.Tasty.HUnit
1922import System.Mem
2023import Test.Alloc
2124
2225import qualified Data.Vector.Unboxed as VU
23-
26+ import Inspect.Fusion
2427
2528tests :: TestTree
2629tests = testGroup " allocations"
@@ -67,8 +70,97 @@ tests = testGroup "allocations"
6770 -- $ checkAllocations (linear 8)
6871 -- $ (\sz -> VU.generateM sz (\n -> Identity (fromIntegral n :: Int64))) `whnf` size
6972 ]
73+ , testGroup " Fusion"
74+ [ testGroup " transformers"
75+ [ allocWHNF " test_map" test_map vectorI
76+ , allocWHNF " test_imap" test_imap vectorI
77+ , allocWHNF " test_mapMaybe" test_mapMaybe vectorI
78+ , allocWHNF " test_cons" test_cons vectorI
79+ , allocWHNF " test_snoc" test_snoc vectorI
80+ -- FIXME: GHC does not fuse intermediate vectors in concatMap
81+ --
82+ -- , allocWHNF "test_concatMap_singleton" test_concatMap_singleton vectorI
83+ -- , allocWHNF "test_concatMap_replicate" test_concatMap_replicate vectorI
84+ , allocWHNF " test_appendL" (test_appendL vectorI) vectorI
85+ , allocWHNF " test_appendR" (test_appendR vectorI) vectorI
86+ , allocWHNF " test_indexed" test_indexed vectorI
87+ ]
88+ , testGroup " producers"
89+ [ allocWHNF " test_replicate" test_replicate size
90+ , allocWHNF " test_generate" test_generate size
91+ , allocWHNF " test_iterateN" test_iterateN size
92+ , allocWHNF " test_unfoldr" test_unfoldr size
93+ , allocWHNF " test_unfoldrN" test_unfoldrN size
94+ , allocWHNF " test_enumFromN" test_enumFromN size
95+ , allocWHNF " test_enumFromStepN" test_enumFromStepN size
96+
97+ , allocWHNF " test_enumFromTo[Int]" (test_enumFromTo @ Int fromIntegral 0 ) 100000
98+ , allocWHNF " test_enumFromTo[Int64]" (test_enumFromTo @ Int64 fromIntegral 0 ) 100000
99+ , allocWHNF " test_enumFromTo[Int32]" (test_enumFromTo @ Int32 fromIntegral 0 ) 100000
100+ , allocWHNF " test_enumFromTo[Int16]" (test_enumFromTo @ Int16 fromIntegral 0 ) maxBound
101+ , allocWHNF " test_enumFromTo[Word]" (test_enumFromTo @ Word fromIntegral 0 ) 100000
102+ , allocWHNF " test_enumFromTo[Word64]" (test_enumFromTo @ Word64 fromIntegral 0 ) 100000
103+ , allocWHNF " test_enumFromTo[Word32]" (test_enumFromTo @ Word32 fromIntegral 0 ) 100000
104+ , allocWHNF " test_enumFromTo[Word16]" (test_enumFromTo @ Word16 fromIntegral 0 ) maxBound
105+ , allocWHNF " test_enumFromTo[Float]" (test_enumFromTo @ Float round 0 ) 100000
106+ , allocWHNF " test_enumFromTo[Double]" (test_enumFromTo @ Double round 0 ) 100000
107+ , allocWHNF " test_enumFromTo[Char]" (test_enumFromTo @ Char ord (chr 32 )) (chr 8000 )
108+ -- FIXME: We don't have specializations for enumFromThenTo
109+ --
110+ -- , allocWHNF "test_enumFromThenTo" test_enumFromThenTo size
111+ ]
112+ , testGroup " consumers"
113+ [ allocWHNF " test_bang" test_bang vectorI
114+ , allocWHNF " test_safeBang" test_safeBang vectorI
115+ , allocWHNF " test_head" test_head vectorI
116+ , allocWHNF " test_last" test_last vectorI
117+ , allocWHNF " test_unsafeHead" test_unsafeHead vectorI
118+ , allocWHNF " test_unsafeLast" test_unsafeLast vectorI
119+ , allocWHNF " test_indexM" test_indexM vectorI
120+ , allocWHNF " test_headM" test_headM vectorI
121+ , allocWHNF " test_lastM" test_lastM vectorI
122+ , allocWHNF " test_unsafeHeadM" test_unsafeHeadM vectorI
123+ , allocWHNF " test_unsafeLastM" test_unsafeLastM vectorI
124+ ]
125+ , testGroup " update"
126+ [ allocVecWHNF " test_upd" (test_upd listUpd) vectorI
127+ , allocVecWHNF " test_update_1" (test_update_1 vectorIdx) vectorI
128+ , allocVecWHNF " test_update_2" (test_update_2 vectorI) vectorI
129+ , allocVecWHNF " test_update__1" (test_update__1 vectorI vectorI) vectorI
130+ , allocVecWHNF " test_update__2" (test_update__2 vectorI vectorI) vectorI
131+ , allocVecWHNF " test_update__3" (test_update__3 vectorI vectorI) vectorI
132+ , allocVecWHNF " test_unsafeUpdate_1" (test_unsafeUpdate_1 vectorIdx) vectorI
133+ , allocVecWHNF " test_unsafeUpdate_2" (test_unsafeUpdate_2 vectorI) vectorI
134+ , allocVecWHNF " test_unsafeUpdate__1" (test_unsafeUpdate__1 vectorI vectorI) vectorI
135+ , allocVecWHNF " test_unsafeUpdate__2" (test_unsafeUpdate__2 vectorI vectorI) vectorI
136+ , allocVecWHNF " test_unsafeUpdate__3" (test_unsafeUpdate__3 vectorI vectorI) vectorI
137+ , allocVecWHNF " test_accumulate_1" (test_accumulate_1 vectorIdx) vectorI
138+ , allocVecWHNF " test_accumulate_2" (test_accumulate_2 vectorI) vectorI
139+ , allocVecWHNF " test_accumulate__1" (test_accumulate__1 vectorI vectorI) vectorI
140+ , allocVecWHNF " test_accumulate__2" (test_accumulate__2 vectorI vectorI) vectorI
141+ , allocVecWHNF " test_accumulate__3" (test_accumulate__3 vectorI vectorI) vectorI
142+ , allocVecWHNF " test_unsafeAccumulate_1" (test_unsafeAccumulate_1 vectorIdx) vectorI
143+ , allocVecWHNF " test_unsafeAccumulate_2" (test_unsafeAccumulate_2 vectorI) vectorI
144+ , allocVecWHNF " test_unsafeAccumulate__1" (test_unsafeAccumulate__1 vectorI vectorI) vectorI
145+ , allocVecWHNF " test_unsafeAccumulate__2" (test_unsafeAccumulate__2 vectorI vectorI) vectorI
146+ , allocVecWHNF " test_unsafeAccumulate__3" (test_unsafeAccumulate__3 vectorI vectorI) vectorI
147+ ]
148+ , testGroup " other"
149+ [ allocWHNF " test_concat" test_concat listVectorI
150+ ]
151+ ]
70152 ]
71153
154+ allocWHNF :: String -> (a -> b ) -> a -> TestTree
155+ {-# INLINE allocWHNF #-}
156+ allocWHNF name f a = testCase name $ checkAllocations constant (f `whnf` a)
157+
158+ allocVecWHNF :: String -> (a -> b ) -> a -> TestTree
159+ {-# INLINE allocVecWHNF #-}
160+ allocVecWHNF name f a
161+ = testCase name
162+ $ checkAllocations (linear (sizeOf (undefined :: Int ))) (f `whnf` a)
163+
72164
73165pureST :: Int -> ST s Int64
74166{-# NOINLINE pureST #-}
@@ -87,6 +179,23 @@ vector :: VU.Vector Int64
87179{-# NOINLINE vector #-}
88180vector = VU. generate size fromIntegral
89181
182+ vectorI :: VU. Vector Int
183+ {-# NOINLINE vectorI #-}
184+ vectorI = VU. generate size fromIntegral
185+
186+ vectorIdx :: VU. Vector (Int ,Int )
187+ {-# NOINLINE vectorIdx #-}
188+ vectorIdx = VU. map (\ i -> (i`div` 3 , i)) vectorI
189+
190+ listVectorI :: [VU. Vector Int ]
191+ {-# NOINLINE listVectorI #-}
192+ listVectorI = replicate 8 vectorI
193+
194+ listUpd :: [(Int ,Int )]
195+ {-# NOINLINE listUpd #-}
196+ listUpd = [(0 ,0 ), (1000 ,0 ), (100 ,0 )]
197+
198+
90199-- | N bytes per element + constant overhead. We also check that bound
91200-- is tight.
92201linear :: Int -> Range
0 commit comments