on master help sign in
Implement partitionBy
21e948aRanjeet Kumar Ranjan
benchmark/Streamly/Benchmark/Data/Mut/Array.hsnew file+96
@@ -0,0 +1,96 @@
1+-- |
2+-- Module : Streamly.Benchmark.Data.Mut.Array
3+-- Copyright : (c) 2020 Composewell Technologies
4+--
5+-- License : BSD-3-Clause
6+-- Maintainer : streamly@composewell.com
7+
8+{-# LANGUAGE CPP #-}
9+{-# LANGUAGE FlexibleContexts #-}
10+{-# LANGUAGE ScopedTypeVariables #-}
11+
12+#ifdef __HADDOCK_VERSION__
13+#undef INSPECTION
14+#endif
15+
16+#ifdef INSPECTION
17+{-# LANGUAGE TemplateHaskell #-}
18+{-# OPTIONS_GHC -fplugin Test.Inspection.Plugin #-}
19+#endif
20+
21+module Main
22+ (
23+ main
24+ ) where
25+
26+import Control.DeepSeq (NFData(..))
27+import System.Random (randomRIO)
28+import Prelude hiding ()
29+
30+import qualified Streamly.Prelude as Stream
31+import qualified Streamly.Internal.Data.Fold as Fold
32+import qualified Streamly.Internal.Data.Array.Stream.Mut.Foreign as MArray
33+
34+import Gauge hiding (env)
35+import Streamly.Prelude (SerialT, MonadAsync, IsStream)
36+import Streamly.Benchmark.Common
37+
38+#ifdef INSPECTION
39+import Foreign.Storable (Storable)
40+import Streamly.Internal.Data.Stream.StreamD.Type (Step(..))
41+import Test.Inspection
42+#endif
43+
44+-------------------------------------------------------------------------------
45+-- Utilities
46+-------------------------------------------------------------------------------
47+
48+{-# INLINE sourceUnfoldrM #-}
49+sourceUnfoldrM :: (IsStream t, MonadAsync m) => Int -> Int -> t m Int
50+sourceUnfoldrM value n = Stream.unfoldrM step n
51+ where
52+ step cnt =
53+ if cnt > n + value
54+ then return Nothing
55+ else return (Just (cnt, cnt + 1))
56+
57+{-# INLINE benchIO #-}
58+benchIO
59+ :: NFData b
60+ => String -> (Int -> t IO a) -> (t IO a -> IO b) -> Benchmark
61+benchIO name src sink =
62+ bench name $ nfIO $ randomRIO (1,1) >>= sink . src
63+
64+{-# INLINE partitionBy #-}
65+partitionBy :: Int -> SerialT IO (MArray.Array Int) -> IO ()
66+partitionBy value s = Stream.fold Fold.drain $ do
67+ a <- s
68+ MArray.partitionBy ( < value) a
69+
70+o_n_space_serial_marray ::
71+ Int -> [MArray.Array Int] -> [Benchmark]
72+o_n_space_serial_marray bound arrays =
73+ [ benchIO "partitionBy" (\_ -> Stream.fromList arrays)
74+ $ partitionBy bound
75+ ]
76+
77+-------------------------------------------------------------------------------
78+-- Driver
79+-------------------------------------------------------------------------------
80+
81+moduleName :: String
82+moduleName = "Data.Mut.Array"
83+
84+main :: IO ()
85+main = do
86+ runWithCLIOptsEnv defaultStreamSize alloc allBenchmarks
87+
88+ where
89+
90+ alloc value =
91+ Stream.toList $ MArray.arraysOf value $ sourceUnfoldrM value 0
92+
93+ allBenchmarks arrays value =
94+ [ bgroup (o_1_space_prefix moduleName) $
95+ o_n_space_serial_marray value arrays
96+ ]
benchmark/streamly-benchmarks.cabal+11
@@ -483,6 +483,17 @@ benchmark Data.Array.Foreign
483 if flag(limit-build-mem)
483 if flag(limit-build-mem)
484 ghc-options: +RTS -M1000M -RTS
484 ghc-options: +RTS -M1000M -RTS
485
485
486+benchmark Data.Mut.Array
487+ import: bench-options
488+ type: exitcode-stdio-1.0
489+ hs-source-dirs: Streamly/Benchmark/Data/Mut
490+ main-is: Array.hs
491+ if impl(ghcjs)
492+ buildable: False
493+ else
494+ buildable: True
495+ build-depends: exceptions >= 0.8 && < 0.11
496+
486-------------------------------------------------------------------------------
497-------------------------------------------------------------------------------
487-- Array Stream Benchmarks
498-- Array Stream Benchmarks
488-------------------------------------------------------------------------------
499-------------------------------------------------------------------------------
src/Streamly/Internal/Data/Array/Foreign/Mut/Type.hs+42−3
@@ -1206,10 +1206,49 @@ permute = undefined
1206-- first half retains values where the predicate is 'False' and the second half
1206-- first half retains values where the predicate is 'False' and the second half
1207-- retains values where the predicate is 'True'.
1207-- retains values where the predicate is 'True'.
1208--
1208--
1209−-- /Unimplemented/
1209+-- /Pre-release/
1210{-# INLINE partitionBy #-}
1210{-# INLINE partitionBy #-}
1211+partitionBy :: forall m a. (MonadIO m, Storable a)
1211−partitionBy :: (a -> Bool) -> Array a -> m (Array a, Array a)
1212+ => (a -> Bool) -> Array a -> m (Array a, Array a)
1212−partitionBy = undefined
1213+partitionBy f arr = do
1214+ let low = 0
1215+ high = length arr - 1
1216+ swap low high arr
1217+
1218+ where
1219+
1220+ findL low = do
1221+ if length arr == low
1222+ then return low
1223+ else do
1224+ fw <- getIndex arr low
1225+ if not (f fw)
1226+ then findL (low + 1)
1227+ else return low
1228+
1229+ findR high = do
1230+ fw <- getIndex arr high
1231+ if f fw && high > 0
1232+ then findR (high - 1)
1233+ else return high
1234+
1235+ swap low high arr0 = do
1236+ if low < high
1237+ then do
1238+ left <- findL low
1239+ right <- findR high
1240+ if left < right
1241+ then do
1242+ unsafeSwapIndices arr0 left right
1243+ swap (left + 1) (right - 1) arr0
1244+ else do
1245+ let al = getSlice 0 left arr0
1246+ ar = getSlice left (length arr0 - left) arr0
1247+ return (al, ar)
1248+ else do
1249+ let al = getSlice 0 low arr0
1250+ ar = getSlice low (length arr0 - low) arr0
1251+ return (al, ar)
1213
1252
1214-- | Shuffle corresponding elements from two arrays using a shuffle function.
1253-- | Shuffle corresponding elements from two arrays using a shuffle function.
1215-- If the shuffle function returns 'False' then do nothing otherwise swap the
1254-- If the shuffle function returns 'False' then do nothing otherwise swap the
src/Streamly/Internal/Data/Array/Stream/Mut/Foreign.hs+3−1
@@ -21,6 +21,8 @@ module Streamly.Internal.Data.Array.Stream.Mut.Foreign
21 , compactLE
21 , compactLE
22 , compactEQ
22 , compactEQ
23 , compactGE
23 , compactGE
24+ , Array(..)
25+ , partitionBy
24 )
26 )
25where
27where
26
28
@@ -32,7 +34,7 @@ import Control.Monad (when)
32import Control.Monad.Catch (MonadThrow)
34import Control.Monad.Catch (MonadThrow)
33import Data.Bifunctor (first)
35import Data.Bifunctor (first)
34import Foreign.Storable (Storable(..))
36import Foreign.Storable (Storable(..))
35−import Streamly.Internal.Data.Array.Foreign.Mut.Type (Array(..))
37+import Streamly.Internal.Data.Array.Foreign.Mut.Type (Array(..), partitionBy)
36import Streamly.Internal.Data.Fold.Type (Fold(..))
38import Streamly.Internal.Data.Fold.Type (Fold(..))
37import Streamly.Internal.Data.Stream.Serial (SerialT(..))
39import Streamly.Internal.Data.Stream.Serial (SerialT(..))
38import Streamly.Internal.Data.Stream.IsStream.Type
40import Streamly.Internal.Data.Stream.IsStream.Type
streamly.cabal+1
@@ -63,6 +63,7 @@ extra-source-files:
63 benchmark/Streamly/Benchmark/Data/Array/Prim.hs
63 benchmark/Streamly/Benchmark/Data/Array/Prim.hs
64 benchmark/Streamly/Benchmark/Data/Array/Prim/Pinned.hs
64 benchmark/Streamly/Benchmark/Data/Array/Prim/Pinned.hs
65 benchmark/Streamly/Benchmark/Data/Array/Stream/Foreign.hs
65 benchmark/Streamly/Benchmark/Data/Array/Stream/Foreign.hs
66+ benchmark/Streamly/Benchmark/Data/Mut/Array.hs
66 benchmark/Streamly/Benchmark/Data/Parser/*.hs
67 benchmark/Streamly/Benchmark/Data/Parser/*.hs
67 benchmark/Streamly/Benchmark/Data/Stream/*.hs
68 benchmark/Streamly/Benchmark/Data/Stream/*.hs
68 benchmark/Streamly/Benchmark/FileSystem/*.hs
69 benchmark/Streamly/Benchmark/FileSystem/*.hs