@@ -520,6 +520,10 @@ writeN n = Fold step initial extract
520520 return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
521521 extract = return -- liftIO . shrinkToFit
522522
523+data ArrayUnsafe a = ArrayUnsafe
524+ {-# UNPACK #-} !(ForeignPtr a) -- first address
525+ {-# UNPACK #-} !(Ptr a) -- first unused address
526+
523527-- | Like 'writeN' but does not check the array bounds when writing. The fold
524528-- driver must not call the step function more than 'n' times otherwise it will
525529-- corrupt the memory and crash. This function exists mainly because any
@@ -534,34 +538,13 @@ writeNUnsafe n = Fold step initial extract
534538
535539 where
536540
537− {-
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
541− -- 10x worse.
542541 initial = do
543542 (Array start end _) <- liftIO $ newArray (max n 0)
544− return (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
547− -- bound pointer.
548− step (start, end) x = do
549− liftIO $ poke end x
550− return $ (start, (end `plusPtr` sizeOf (undefined :: a)))
551− extract (start, end) = return $ Array start end end -- liftIO . shrinkToFit
552− -}
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
558− -- implementation.
559− initial = do
560− liftIO $ newArray (max n 0)
561− step (Array start end bound) x = do
543+ return $ ArrayUnsafe start end
544+ step (ArrayUnsafe start end) x = do
562545 liftIO $ poke end x
563− return $ Array start (end `plusPtr` sizeOf (undefined :: a)) bound
564− extract = return -- liftIO . shrinkToFit
546+ return $ (ArrayUnsafe start (end `plusPtr` sizeOf (undefined :: a)))
547+ extract (ArrayUnsafe start end) = return $ Array start end end -- liftIO . shrinkToFit
565548
566549{-# INLINE_NORMAL fromStreamDN #-}
567550fromStreamDN :: forall m a. (MonadIO m, Storable a)