@@ -29,7 +29,7 @@ module Streamly.Internal.Data.Array.Foreign.Mut.Type
30 -- * Resizing
30 -- * Resizing
32− , shrinkToFit
32+ , rightSize
@@ -533,18 +533,28 @@ realloc i arr =
533 $ reallocAligned
533 $ reallocAligned
534 (sizeOf (undefined :: a)) (alignment (undefined :: a)) i arr
534 (sizeOf (undefined :: a)) (alignment (undefined :: a)) i arr
536−-- | Remove the free space from an Array.
536+-- | Drop any reserved free space at the end of the array and reallocate it to
537−{-# INLINE shrinkToFit #-}
537+-- reduce wastage.
539+-- Up to 25% wastage is allowed to avoid reallocations. If the capacity is
540+-- more than 'largeObjectThreshold' then free space up to the 'blockSize' is
544+{-# INLINE rightSize #-}
538−shrinkToFit :: (MonadIO m, Storable a) => Array a -> m (Array a)
545+rightSize :: forall m a. (MonadIO m, Storable a) => Array a -> m (Array a)
539−shrinkToFit arr@Array{..} = do
546+rightSize arr@Array{..} = do
540 assert (aEnd <= aBound) (return ())
547 assert (aEnd <= aBound) (return ())
541 let start = unsafeForeignPtrToPtr aStart
548 let start = unsafeForeignPtrToPtr aStart
542− let used = aEnd `minusPtr` start
549+ len = aEnd `minusPtr` start
550+ capacity = aBound `minusPtr` start
551+ target = roundUpLargeArray len
543 waste = aBound `minusPtr` aEnd
552 waste = aBound `minusPtr` aEnd
544− -- if used == waste == 0 then do not realloc
553+ assert (target >= len) (return ())
545− -- if the wastage is more than 25% of the array then realloc
554+ assert (len `mod` sizeOf (undefined :: a) == 0) (return ())
555+ -- We trade off some wastage (25%) to avoid reallocations and copying.
546− if used < 3 * waste
556+ if target < capacity && len < 3 * waste
547− then realloc used arr
557+ then realloc target arr
548 else return arr
558 else return arr
550-------------------------------------------------------------------------------
560-------------------------------------------------------------------------------
@@ -1106,7 +1116,7 @@ writeWith alignSize elemCount =
1106 (sizeOf (undefined :: a)) alignSize newSize arr
1116 (sizeOf (undefined :: a)) alignSize newSize arr
1107 insertElem arr1 x
1117 insertElem arr1 x
1108 step arr x = insertElem arr x
1118 step arr x = insertElem arr x
1109− extract = liftIO . shrinkToFit
1119+ extract = liftIO . rightSize
1111-- | Fold the whole input to a single array.
1121-- | Fold the whole input to a single array.