@@ -520,6 +520,10 @@ writeN n = Fold step initial extract
520 return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
520 return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
521 extract = return -- liftIO . shrinkToFit
521 extract = return -- liftIO . shrinkToFit
523+data ArrayUnsafe a = ArrayUnsafe
524+ {-# UNPACK #-} !(ForeignPtr a) -- first address
525+ {-# UNPACK #-} !(Ptr a) -- first unused address
523-- | Like 'writeN' but does not check the array bounds when writing. The fold
527-- | Like 'writeN' but does not check the array bounds when writing. The fold
524-- driver must not call the step function more than 'n' times otherwise it will
528-- driver must not call the step function more than 'n' times otherwise it will
525-- corrupt the memory and crash. This function exists mainly because any
529-- corrupt the memory and crash. This function exists mainly because any
@@ -534,34 +538,13 @@ writeNUnsafe n = Fold step initial extract
538− -- XXX this implementation is good on all benchmarks except
539− -- readStream/catStream which uses a stream based writeS instead of a fold
540− -- based write. In the writeS case it does not fuse and therefore performs
542 initial = do
541 initial = do
543 (Array start end _) <- liftIO $ newArray (max n 0)
542 (Array start end _) <- liftIO $ newArray (max n 0)
544− return (start, end)
543+ return $ ArrayUnsafe start end
545− -- XXX any if condition in the step causes fusion to fail with groupsOf
546− -- If we need to do bounds check we can use 'n' instead of threading around
548− step (start, end) x = do
550− return $ (start, (end `plusPtr` sizeOf (undefined :: a)))
551− extract (start, end) = return $ Array start end end -- liftIO . shrinkToFit
553− -- This implementation fuses in all known cases as of now. Even though both
554− -- readStream/cat and readStream/catStream benchmarks perform 2x worse when
555− -- arraysOf uses this impl compared to their best seen performance.
556− -- readStream/cat is best with the above implementation and
557− -- readStream/catStream is best when using the custom arraysOf
560− liftIO $ newArray (max n 0)
561− step (Array start end bound) x = do
544+ step (ArrayUnsafe start end) x = do
562 liftIO $ poke end x
545 liftIO $ poke end x
563− return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
546+ return $ (ArrayUnsafe start (end `plusPtr` sizeOf (undefined :: a)))
564− extract = return -- liftIO . shrinkToFit
547+ extract (ArrayUnsafe start end) = return $ Array start end end -- liftIO . shrinkToFit
566{-# INLINE_NORMAL fromStreamDN #-}
549{-# INLINE_NORMAL fromStreamDN #-}
567fromStreamDN :: forall m a. (MonadIO m, Storable a)
550fromStreamDN :: forall m a. (MonadIO m, Storable a)