on master help sign in
Use unsafe peek and poke for better performance
06ae33eHarendra Kumar
benchmark/Streamly/Benchmark/Data/Unbox.hs+71−41
@@ -1,5 +1,11 @@
1{-# LANGUAGE TemplateHaskell #-}
1{-# LANGUAGE TemplateHaskell #-}
2
2
3+#undef FUSION_CHECK
4+#ifdef FUSION_CHECK
5+{-# OPTIONS_GHC -ddump-simpl -ddump-to-file -dsuppress-all #-}
6+#endif
7+
8+
3-- |
9-- |
4-- Module : Streamly.Benchmark.Data.Unbox
10-- Module : Streamly.Benchmark.Data.Unbox
5-- Copyright : (c) 2023 Composewell
11-- Copyright : (c) 2023 Composewell
@@ -20,7 +26,9 @@ import GHC.Generics (Generic)
20import System.Random (randomRIO)
26import System.Random (randomRIO)
21
27
22import Streamly.Internal.Data.Unbox
28import Streamly.Internal.Data.Unbox
29+#ifdef USE_TH
23import Streamly.Internal.Data.Unbox.TH
30import Streamly.Internal.Data.Unbox.TH
31+#endif
24
32
25import Gauge
33import Gauge
26import Streamly.Benchmark.Common
34import Streamly.Benchmark.Common
@@ -29,30 +37,41 @@ import Streamly.Benchmark.Common
29-- Types
37-- Types
30-------------------------------------------------------------------------------
38-------------------------------------------------------------------------------
31
39
32−data CustomDT1 a b
40+data CustomDT1
33 = CDT1C1
41 = CDT1C1
34− | CDT1C2 a
42+ | CDT1C2 Int
35− | CDT1C3 a b
43+ | CDT1C3 Int Bool
36 deriving (Generic, Show, Eq)
44 deriving (Generic, Show, Eq)
37−type CustomDT1_ = CustomDT1 Int Bool
38−
39−instance (Unbox a, Unbox b) => Unbox (CustomDT1 a b)
40
45
41−data CustomDT2 a b
46+#ifndef USE_TH
42− = CDT2C1
47+instance Unbox CustomDT1
43− | CDT2C2 a
48+#else
44− | CDT2C3 a b
45− deriving (Show, Eq)
46−type CustomDT2_ = CustomDT2 Int Bool
47−
48−$(deriveUnbox ''CustomDT2)
49+$(deriveUnbox ''CustomDT1)
50+#endif
49
51
50-------------------------------------------------------------------------------
52-------------------------------------------------------------------------------
51-- Helpers
53-- Helpers
52-------------------------------------------------------------------------------
54-------------------------------------------------------------------------------
53
55
56+{-# INLINE pokeTimes #-}
57+pokeTimes :: forall a. Unbox a => a -> Int -> IO ()
58+pokeTimes val times = do
59+ arr <- newBytes (sizeOf (Proxy :: Proxy a))
60+ replicateM_ times $ do
61+ pokeByteIndex 0 arr val
62+
63+{-# INLINE peekTimes #-}
64+peekTimes :: forall a. Unbox a => a -> Int -> IO ()
65+peekTimes val times = do
66+ arr <- newBytes (sizeOf (Proxy :: Proxy a))
67+ pokeByteIndex 0 arr val
68+ replicateM_ times $ do
69+ (_ :: a) <- peekByteIndex 0 arr
70+ return ()
71+
72+{-# INLINE roundtrip #-}
54−serializeDeserializeTimes :: forall a. (Eq a, Unbox a) => a -> Int -> IO ()
73+roundtrip :: forall a. (Eq a, Unbox a) => a -> Int -> IO ()
55−serializeDeserializeTimes val times = do
74+roundtrip val times = do
56 arr <- newBytes (sizeOf (Proxy :: Proxy a))
75 arr <- newBytes (sizeOf (Proxy :: Proxy a))
57 replicateM_ times $ do
76 replicateM_ times $ do
58 pokeByteIndex 0 arr val
77 pokeByteIndex 0 arr val
@@ -68,30 +87,30 @@ benchSink name times f = bench name (nfIO (randomRIO (times, times) >>= f))
68
87
69allBenchmarks :: Int -> [Benchmark]
88allBenchmarks :: Int -> [Benchmark]
70allBenchmarks times =
89allBenchmarks times =
71− [ benchSink
90+ [ bgroup "poke"
72− "serializeDeserializeTimes CDT1C1 (Generic)"
73− times
91+ [ benchSink "C1" times
74− (serializeDeserializeTimes (CDT1C1 :: CustomDT1_))
92+ (pokeTimes (CDT1C1 :: CustomDT1))
75− , benchSink
93+ , benchSink "C2" times
76− "serializeDeserializeTimes CDT2C1 (TH)"
94+ (pokeTimes ((CDT1C2 (5 :: Int)) :: CustomDT1))
77− times
95+ , benchSink "C3" times
78− (serializeDeserializeTimes (CDT2C1 :: CustomDT2_))
96+ (pokeTimes ((CDT1C3 (5 :: Int) True) :: CustomDT1))
79− , benchSink
97+ ]
80− "serializeDeserializeTimes CDT1C2 (Generic)"
98+ , bgroup "peek"
99+ [ benchSink "C1" times
100+ (peekTimes (CDT1C1 :: CustomDT1))
81− times
101+ , benchSink "C2" times
82− (serializeDeserializeTimes ((CDT1C2 (5 :: Int)) :: CustomDT1_))
102+ (peekTimes ((CDT1C2 (5 :: Int)) :: CustomDT1))
83− , benchSink
103+ , benchSink "C3" times
84− "serializeDeserializeTimes CDT2C2 (TH)"
104+ (peekTimes ((CDT1C3 (5 :: Int) True) :: CustomDT1))
85− times
105+ ]
86− (serializeDeserializeTimes ((CDT2C2 (5 :: Int)) :: CustomDT2_))
106+ , bgroup "roundtrip"
87− , benchSink
107+ [ benchSink "C1" times
88− "serializeDeserializeTimes CDT1C3 (Generic)"
108+ (roundtrip (CDT1C1 :: CustomDT1))
89− times
109+ , benchSink "C2" times
90− (serializeDeserializeTimes ((CDT1C3 (5 :: Int) True) :: CustomDT1_))
110+ (roundtrip ((CDT1C2 (5 :: Int)) :: CustomDT1))
91− , benchSink
111+ , benchSink "C3" times
92− "serializeDeserializeTimes CDT2C3 (TH)"
112+ (roundtrip ((CDT1C3 (5 :: Int) True) :: CustomDT1))
93− times
113+ ]
94− (serializeDeserializeTimes ((CDT2C3 (5 :: Int) True) :: CustomDT2_))
95 ]
114 ]
96
115
97-------------------------------------------------------------------------------
116-------------------------------------------------------------------------------
@@ -99,4 +118,15 @@ allBenchmarks times =
99-------------------------------------------------------------------------------
118-------------------------------------------------------------------------------
100
119
101main :: IO ()
120main :: IO ()
121+main = do
122+#ifndef FUSION_CHECK
102−main = runWithCLIOpts defaultStreamSize allBenchmarks
123+ runWithCLIOpts defaultStreamSize allBenchmarks
124+#else
125+ -- Enable FUSION_CHECK macro at the beginning of the file
126+ -- Enable one benchmark below, and run the benchmark
127+ -- Check the .dump-simpl output
128+ let value = 100000
129+ -- peekTimes ((CDT1C2 (5 :: Int)) :: CustomDT1) value
130+ roundtrip ((CDT1C2 (5 :: Int)) :: CustomDT1) value
131+ return ()
132+#endif
benchmark/streamly-benchmarks.cabal+7
@@ -362,6 +362,13 @@ benchmark Data.Unbox
362 hs-source-dirs: .
362 hs-source-dirs: .
363 main-is: Streamly/Benchmark/Data/Unbox.hs
363 main-is: Streamly/Benchmark/Data/Unbox.hs
364
364
365+benchmark Data.Unbox.Derive.TH
366+ import: bench-options
367+ type: exitcode-stdio-1.0
368+ hs-source-dirs: .
369+ cpp-options: -DUSE_TH
370+ main-is: Streamly/Benchmark/Data/Unbox.hs
371+
365benchmark Data.Unfold
372benchmark Data.Unfold
366 import: bench-options
373 import: bench-options
367 type: exitcode-stdio-1.0
374 type: exitcode-stdio-1.0
core/src/Streamly/Internal/Data/Unbox.hs+69−12
@@ -100,6 +100,7 @@ touch :: MutableByteArray -> IO ()
100touch (MutableByteArray contents) =
100touch (MutableByteArray contents) =
101 IO $ \s -> case touch# contents s of s' -> (# s', () #)
101 IO $ \s -> case touch# contents s of s' -> (# s', () #)
102
102
103+{-
103-- | Return the size of the array in bytes.
104-- | Return the size of the array in bytes.
104{-# INLINE sizeOfMutableByteArray #-}
105{-# INLINE sizeOfMutableByteArray #-}
105sizeOfMutableByteArray :: MutableByteArray -> IO Int
106sizeOfMutableByteArray :: MutableByteArray -> IO Int
@@ -107,6 +108,7 @@ sizeOfMutableByteArray (MutableByteArray arr) =
107 IO $ \s ->
108 IO $ \s ->
108 case getSizeofMutableByteArray# arr s of
109 case getSizeofMutableByteArray# arr s of
109 (# s1, i #) -> (# s1, I# i #)
110 (# s1, i #) -> (# s1, I# i #)
111+-}
110
112
111--------------------------------------------------------------------------------
113--------------------------------------------------------------------------------
112-- Creation
114-- Creation
@@ -282,7 +284,9 @@ unpin arr@(MutableByteArray marr#) =
282-- The 'peekByteIndex' read operation converts a Haskell type from its unboxed
284-- The 'peekByteIndex' read operation converts a Haskell type from its unboxed
283-- representation stored in a mutable byte array, while the 'pokeByteIndex'
285-- representation stored in a mutable byte array, while the 'pokeByteIndex'
284-- write operation serializes a Haskell data type to its byte representation in
286-- write operation serializes a Haskell data type to its byte representation in
285−-- the mutable byte array.
287+-- the mutable byte array. These operations do not check the bounds of the
288+-- array, the user of the type class is expected to check the bounds before
289+-- peeking or poking.
286--
290--
287-- Instances can be derived via Generics or Template Haskell. Note that the
291-- Instances can be derived via Generics or Template Haskell. Note that the
288-- data type must be non-recursive.
292-- data type must be non-recursive.
@@ -326,10 +330,12 @@ unpin arr@(MutableByteArray marr#) =
326-- instance Unbox Object where
330-- instance Unbox Object where
327-- sizeOf _ = 16
331-- sizeOf _ = 16
328-- peekByteIndex i arr = do
332-- peekByteIndex i arr = do
333+-- -- Check the array bounds
329-- x0 <- peekByteIndex i arr
334-- x0 <- peekByteIndex i arr
330-- x1 <- peekByteIndex (i + 8) arr
335-- x1 <- peekByteIndex (i + 8) arr
331-- return $ Object x0 x1
336-- return $ Object x0 x1
332-- pokeByteIndex i arr (Object x0 x1) = do
337-- pokeByteIndex i arr (Object x0 x1) = do
338+-- -- Check the array bounds
333-- pokeByteIndex i arr x0
339-- pokeByteIndex i arr x0
334-- pokeByteIndex (i + 8) arr x1
340-- pokeByteIndex (i + 8) arr x1
335-- :}
341-- :}
@@ -587,6 +593,12 @@ readUnsafe = Peeker (Builder step)
587 step :: forall a. Unbox a => BoundedPtr -> IO (BoundedPtr, a)
593 step :: forall a. Unbox a => BoundedPtr -> IO (BoundedPtr, a)
588 step (BoundedPtr arr pos end) = do
594 step (BoundedPtr arr pos end) = do
589 let next = pos + sizeOf (Proxy :: Proxy a)
595 let next = pos + sizeOf (Proxy :: Proxy a)
596+#ifdef DEBUG
597+ when (next > end)
598+ $ error $ "readUnsafe: reading beyond limit. next = "
599+ ++ show next
600+ ++ " end = " ++ show end
601+#endif
590 r <- peekByteIndex pos arr
602 r <- peekByteIndex pos arr
591 return (BoundedPtr arr next end, r)
603 return (BoundedPtr arr next end, r)
592
604
@@ -600,7 +612,10 @@ read = Peeker (Builder step)
600 step :: forall a. Unbox a => BoundedPtr -> IO (BoundedPtr, a)
612 step :: forall a. Unbox a => BoundedPtr -> IO (BoundedPtr, a)
601 step (BoundedPtr arr pos end) = do
613 step (BoundedPtr arr pos end) = do
602 let next = pos + sizeOf (Proxy :: Proxy a)
614 let next = pos + sizeOf (Proxy :: Proxy a)
615+ when (next > end)
603− when (next > end) $ error "peekObject reading beyond limit"
616+ $ error $ "read: reading beyond limit. next = "
617+ ++ show next
618+ ++ " end = " ++ show end
604 r <- peekByteIndex pos arr
619 r <- peekByteIndex pos arr
605 return (BoundedPtr arr next end, r)
620 return (BoundedPtr arr next end, r)
606
621
@@ -614,10 +629,12 @@ skipByte = Peeker (Builder step)
614 step :: BoundedPtr -> IO (BoundedPtr, ())
629 step :: BoundedPtr -> IO (BoundedPtr, ())
615 step (BoundedPtr arr pos end) = do
630 step (BoundedPtr arr pos end) = do
616 let next = pos + 1
631 let next = pos + 1
632+#ifdef DEBUG
617 when (next > end)
633 when (next > end)
618 $ error $ "skipByte: reading beyond limit. next = "
634 $ error $ "skipByte: reading beyond limit. next = "
619 ++ show next
635 ++ show next
620 ++ " end = " ++ show end
636 ++ " end = " ++ show end
637+#endif
621 return (BoundedPtr arr next end, ())
638 return (BoundedPtr arr next end, ())
622
639
623{-# INLINE runPeeker #-}
640{-# INLINE runPeeker #-}
@@ -638,6 +655,12 @@ runPeeker (Peeker (Builder f)) ptr = fmap snd (f ptr)
638pokeBoundedPtrUnsafe :: forall a. Unbox a => a -> BoundedPtr -> IO BoundedPtr
655pokeBoundedPtrUnsafe :: forall a. Unbox a => a -> BoundedPtr -> IO BoundedPtr
639pokeBoundedPtrUnsafe a (BoundedPtr arr pos end) = do
656pokeBoundedPtrUnsafe a (BoundedPtr arr pos end) = do
640 let next = pos + sizeOf (Proxy :: Proxy a)
657 let next = pos + sizeOf (Proxy :: Proxy a)
658+#ifdef DEBUG
659+ when (next > end)
660+ $ error $ "pokeBoundedPtrUnsafe: reading beyond limit. next = "
661+ ++ show next
662+ ++ " end = " ++ show end
663+#endif
641 pokeByteIndex pos arr a
664 pokeByteIndex pos arr a
642 return (BoundedPtr arr next end)
665 return (BoundedPtr arr next end)
643
666
@@ -669,7 +692,10 @@ type family ArityCheck (b :: Bool) :: Constraint where
669
692
670-- Type constraint to restrict the sum type arity so that the constructor tag
693-- Type constraint to restrict the sum type arity so that the constructor tag
671-- can fit in a single byte.
694-- can fit in a single byte.
695+-- Note that Arity starts from 1 and constructor tags start from 0. So if max
696+-- arity is 256 then max constructor tag would be 255.
697+-- XXX Use variable length encoding to support more than 256 constructors.
672−type MaxArity256 n = ArityCheck (n <=? 255)
698+type MaxArity256 n = ArityCheck (n <=? 256)
673
699
674--------------------------------------------------------------------------------
700--------------------------------------------------------------------------------
675-- Generic Deriving of Unbox instance
701-- Generic Deriving of Unbox instance
@@ -735,8 +761,8 @@ instance (MaxArity256 (SumArity (f :+: g)), SizeOfRepSum f, SizeOfRepSum g) =>
735
761
736 -- The size of a sum type is the max of any of the constructor size.
762 -- The size of a sum type is the max of any of the constructor size.
737 -- sizeOfRepSum type class operation is used here instead of sizeOfRep so
763 -- sizeOfRepSum type class operation is used here instead of sizeOfRep so
738− -- that we add the constructor index byte only for the first time and avoid
764+ -- that we account the constructor index byte only for the first time and
739− -- including it for the subsequent sum constructors.
765+ -- avoid including it for the subsequent sum constructors.
740 {-# INLINE sizeOfRep #-}
766 {-# INLINE sizeOfRep #-}
741 sizeOfRep _ =
767 sizeOfRep _ =
742 -- One byte for the constructor id and then the constructor value.
768 -- One byte for the constructor id and then the constructor value.
@@ -753,6 +779,12 @@ instance (MaxArity256 (SumArity (f :+: g)), SizeOfRepSum f, SizeOfRepSum g) =>
753-- elements to make the size as 1. Or we can disallow arrays with elements
779-- elements to make the size as 1. Or we can disallow arrays with elements
754-- having size 0.
780-- having size 0.
755--
781--
782+-- Some examples:
783+--
784+-- data B = B -- one byte
785+-- data A = A B -- one byte
786+-- data X = X1 | X2 -- one byte (constructor tag only)
787+--
756{-# INLINE genericSizeOf #-}
788{-# INLINE genericSizeOf #-}
757genericSizeOf :: forall a. (SizeOfRep (Rep a)) => Proxy a -> Int
789genericSizeOf :: forall a. (SizeOfRep (Rep a)) => Proxy a -> Int
758genericSizeOf _ =
790genericSizeOf _ =
@@ -772,7 +804,7 @@ instance PokeRep f => PokeRep (M1 i c f) where
772
804
773instance Unbox a => PokeRep (K1 i a) where
805instance Unbox a => PokeRep (K1 i a) where
774 {-# INLINE pokeRep #-}
806 {-# INLINE pokeRep #-}
775− pokeRep a = pokeBoundedPtr (unK1 a)
807+ pokeRep a = pokeBoundedPtrUnsafe (unK1 a)
776
808
777instance PokeRep V1 where
809instance PokeRep V1 where
778 {-# INLINE pokeRep #-}
810 {-# INLINE pokeRep #-}
@@ -795,8 +827,8 @@ class KnownNat n => PokeRepSum (n :: Nat) (f :: Type -> Type) where
795instance (KnownNat n, PokeRep a) => PokeRepSum n (C1 c a) where
827instance (KnownNat n, PokeRep a) => PokeRepSum n (C1 c a) where
796 {-# INLINE pokeRepSum #-}
828 {-# INLINE pokeRepSum #-}
797 pokeRepSum _ x ptr = do
829 pokeRepSum _ x ptr = do
798− pokeBoundedPtr (fromInteger (natVal (Proxy :: Proxy n)) :: Word8) ptr
830+ let tag = fromInteger (natVal (Proxy :: Proxy n)) :: Word8
799− >>= pokeRep x
831+ pokeBoundedPtrUnsafe tag ptr >>= pokeRep x
800
832
801instance (PokeRepSum n f, PokeRepSum (n + SumArity f) g)
833instance (PokeRepSum n f, PokeRepSum (n + SumArity f) g)
802 => PokeRepSum n (f :+: g) where
834 => PokeRepSum n (f :+: g) where
@@ -827,14 +859,20 @@ genericPokeByteIndex :: (Generic a, PokeRep (Rep a)) =>
827 MutableByteArray -> Int -> a -> IO ()
859 MutableByteArray -> Int -> a -> IO ()
828genericPokeByteIndex arr index x = do
860genericPokeByteIndex arr index x = do
829 -- XXX Should we use unsafe poke?
861 -- XXX Should we use unsafe poke?
862+#ifdef DEBUG
830 end <- sizeOfMutableByteArray arr
863 end <- sizeOfMutableByteArray arr
831 genericPokeObj x (BoundedPtr arr index end)
864 genericPokeObj x (BoundedPtr arr index end)
865+#else
866+ genericPokeObj x (BoundedPtr arr index undefined)
867+#endif
832
868
833--------------------------------------------------------------------------------
869--------------------------------------------------------------------------------
834-- Generic peek
870-- Generic peek
835--------------------------------------------------------------------------------
871--------------------------------------------------------------------------------
836
872
837class PeekRep (f :: Type -> Type) where
873class PeekRep (f :: Type -> Type) where
874+ -- Like pokeRep, we can use the following signature instead of using Peeker
875+ -- peekRep :: BoundedPtr -> IO (BoundedPtr, f a)
838 peekRep :: Peeker (f x)
876 peekRep :: Peeker (f x)
839
877
840instance PeekRep f => PeekRep (M1 i c f) where
878instance PeekRep f => PeekRep (M1 i c f) where
@@ -843,7 +881,7 @@ instance PeekRep f => PeekRep (M1 i c f) where
843
881
844instance Unbox a => PeekRep (K1 i a) where
882instance Unbox a => PeekRep (K1 i a) where
845 {-# INLINE peekRep #-}
883 {-# INLINE peekRep #-}
846− peekRep = fmap K1 read
884+ peekRep = fmap K1 readUnsafe
847
885
848instance PeekRep V1 where
886instance PeekRep V1 where
849 {-# INLINE peekRep #-}
887 {-# INLINE peekRep #-}
@@ -865,6 +903,11 @@ class KnownNat n => PeekRepSum (n :: Nat) (f :: Type -> Type) where
865
903
866instance (KnownNat n, PeekRep a) => PeekRepSum n (C1 c a) where
904instance (KnownNat n, PeekRep a) => PeekRepSum n (C1 c a) where
867 {-# INLINE peekRepSum #-}
905 {-# INLINE peekRepSum #-}
906+ peekRepSum _ _ = peekRep
907+ {-
908+ -- These error checks are expensive, to avoid these
909+ -- we validate the max value of the tag in peekRep.
910+ -- XXX Add tests to cover all cases
868 peekRepSum _ tag
911 peekRepSum _ tag
869 | tag == curTag = peekRep
912 | tag == curTag = peekRep
870 | tag > curTag =
913 | tag > curTag =
@@ -876,6 +919,7 @@ instance (KnownNat n, PeekRep a) => PeekRepSum n (C1 c a) where
876 where
919 where
877
920
878 curTag = fromInteger (natVal (Proxy :: Proxy n))
921 curTag = fromInteger (natVal (Proxy :: Proxy n))
922+ -}
879
923
880instance (PeekRepSum n f, PeekRepSum (n + SumArity f) g)
924instance (PeekRepSum n f, PeekRepSum (n + SumArity f) g)
881 => PeekRepSum n (f :+: g) where
925 => PeekRepSum n (f :+: g) where
@@ -892,12 +936,21 @@ instance (PeekRepSum n f, PeekRepSum (n + SumArity f) g)
892
936
893-------------------------------------------------------------------------------
937-------------------------------------------------------------------------------
894
938
895−instance (MaxArity256 (SumArity (f :+: g)), PeekRepSum 0 (f :+: g))
939+instance ( MaxArity256 (SumArity (f :+: g))
940+ , KnownNat (SumArity (f :+: g))
941+ , PeekRepSum 0 (f :+: g))
896 => PeekRep (f :+: g) where
942 => PeekRep (f :+: g) where
897 {-# INLINE peekRep #-}
943 {-# INLINE peekRep #-}
898 peekRep = do
944 peekRep = do
899− tag <- read
945+ tag :: Word8 <- readUnsafe
946+ -- XXX test with 256 and more constructors
947+ let arity :: Int =
948+ fromInteger (natVal (Proxy :: Proxy (SumArity (f :+: g))))
949+ when (fromIntegral tag >= arity)
950+ $ error $ "peek: Tag " ++ show tag
951+ ++ " is greater than the max tag " ++ show (arity - 1)
952+ ++ " for the data type"
900− peekRepSum (Proxy :: Proxy 0) tag
953+ peekRepSum (Proxy :: Proxy 0) tag -- DataKinds
901
954
902{-# INLINE genericPeeker #-}
955{-# INLINE genericPeeker #-}
903genericPeeker :: (Generic a, PeekRep (Rep a)) => Peeker a
956genericPeeker :: (Generic a, PeekRep (Rep a)) => Peeker a
@@ -912,5 +965,9 @@ genericPeekByteIndex :: (Generic a, PeekRep (Rep a)) =>
912 MutableByteArray -> Int -> IO a
965 MutableByteArray -> Int -> IO a
913genericPeekByteIndex arr index = do
966genericPeekByteIndex arr index = do
914 -- XXX Should we use unsafe peek?
967 -- XXX Should we use unsafe peek?
968+#ifdef DEBUG
915 end <- sizeOfMutableByteArray arr
969 end <- sizeOfMutableByteArray arr
916 genericPeekBoundedPtr (BoundedPtr arr index end)
970 genericPeekBoundedPtr (BoundedPtr arr index end)
971+#else
972+ genericPeekBoundedPtr (BoundedPtr arr index undefined)
973+#endif
targets/Targets.hs+2−1
@@ -187,7 +187,8 @@ targets =
187 , ("Data.Fold.Window", [ "parser_grp", "infinite_grp" ])
187 , ("Data.Fold.Window", [ "parser_grp", "infinite_grp" ])
188 , ("Data.Parser", [ "parser_grp", "infinite_grp" ])
188 , ("Data.Parser", [ "parser_grp", "infinite_grp" ])
189
189
190− , ("Data.Unbox", ["noBench"])
190+ , ("Data.Unbox", [])
191+ , ("Data.Unbox.Derive.TH", [])
191 , ("Data.Unfold", ["infinite_grp"])
192 , ("Data.Unfold", ["infinite_grp"])
192 , ("FileSystem.Handle", [])
193 , ("FileSystem.Handle", [])
193 , ("Unicode.Stream", [])
194 , ("Unicode.Stream", [])