@@ -81,7 +81,7 @@ module Streamly.Memory.Array
8181 -- Monadic APIs
8282 -- , newArray
8383 , A.writeN -- drop new
84− , write -- full buffer
84+ , A.write -- full buffer
8585 -- , writeLastN -- drop old (ring buffer)
8686
8787 -- Stream Folds
@@ -137,12 +137,9 @@ module Streamly.Memory.Array
137137 )
138138where
139139
140−import Control.Monad (when)
141140import Control.Monad.IO.Class (MonadIO(..))
142141-- import Data.Functor.Identity (Identity)
143142import Foreign.ForeignPtr (withForeignPtr)
144−import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
145−import Foreign.Ptr (minusPtr, plusPtr)
146143import Foreign.Storable (Storable(..))
147144import Prelude hiding (length, null, last, map, (!!), read, concat)
148145
@@ -180,51 +177,6 @@ _writeNS n m = do
180177 if n < 0 then error "writeN: negative write count specified" else return ()
181178 A.fromStreamDN n $ D.toStreamD m
182179
183−-- XXX The realloc based implementation needs to make one extra copy if we use
184−-- shrinkToFit. On the other hand, the stream of arrays implementation may
185−-- buffer the array chunk pointers in memory but it does not have to shrink as
186−-- we know the exact size in the end. However, memory copying does not seems to
187−-- be as expensive as the allocations. Therefore, we need to reduce the number
188−-- of allocations instead. Also, the size of allocations matters, right sizing
189−-- an allocation even at the cost of copying sems to help. Should be measured
190−-- on a big stream with heavy calls to toArray to see the effect.
191−--
192−-- XXX check if GHC's memory allocator is efficient enough. We can try the C
193−-- malloc to compare against.
194−
195−{-# INLINE_NORMAL toArrayMinChunk #-}
196−toArrayMinChunk :: forall m a. (MonadIO m, Storable a)
197− => Int -> Fold m a (Array a)
198−-- toArrayMinChunk n = FL.mapM spliceArrays $ toArraysOf n
199−toArrayMinChunk elemCount = Fold step initial extract
200−
201− where
202−
203− insertElem (Array start end bound) x = do
204− liftIO $ poke end x
205− return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
206−
207− initial = do
208− when (elemCount < 0) $ error "toArrayMinChunk: elemCount is negative"
209− liftIO $ A.newArray elemCount
210− step arr@(Array start end bound) x | end == bound = do
211− let p = unsafeForeignPtrToPtr start
212− oldSize = end `minusPtr` p
213− newSize = max (oldSize * 2) 1
214− arr1 <- liftIO $ A.realloc newSize arr
215− insertElem arr1 x
216− step arr x = insertElem arr x
217− extract = liftIO . A.shrinkToFit
218−
219−-- | Fold the whole input to a single array.
220−--
221−-- /Caution! Do not use this on infinite streams./
222−--
223−-- @since 0.7.0
224−{-# INLINE write #-}
225−write :: forall m a. (MonadIO m, Storable a) => Fold m a (Array a)
226−write = toArrayMinChunk (A.bytesToElemCount (undefined :: a) (A.mkChunkSize 1024))
227−
228180-- | Create an 'Array' from a stream. This is useful when we want to create a
229181-- single array from a stream of unknown size. 'writeN' is at least twice
230182-- as efficient when the size is already known.
@@ -235,7 +187,7 @@ write = toArrayMinChunk (A.bytesToElemCount (undefined :: a) (A.mkChunkSize 1024
235187--
236188{-# INLINE _writeS #-}
237189_writeS :: (MonadIO m, Storable a) => SerialT m a -> m (Array a)
238−_writeS = P.runFold write
190+_writeS = P.runFold A.write
239191-- write m = A.fromStreamD $ D.toStreamD m
240192
241193-------------------------------------------------------------------------------
@@ -458,7 +410,7 @@ runPipe f arr = P.runPipe (toArrayMinChunk (length arr)) $ f (A.read arr)
458410{-# INLINE _runTransform #-}
459411_runTransform :: (MonadIO m, Storable a, Storable b)
460412 => (SerialT m a -> SerialT m b) -> Array a -> m (Array b)
461−_runTransform f arr = P.runFold (toArrayMinChunk (length arr)) $ f (A.read arr)
413+_runTransform f arr = P.runFold (A.toArrayMinChunk (length arr)) $ f (A.read arr)
462414
463415-- | Fold an array using a 'Fold'.
464416--