on master help sign in
Revert to using a separate GroupConsume state
commitdd8bd7d2759d4f8a9fbab4cbf911233600d37ca2 authorHarendra Kumar <harendra@composewell.com> dateThu 17 Dec 2020, 15:07 (6 years ago) parent6bc64a4
2 files changed+23−19
design/optimization-guidelines.md+4 src/Streamly/Internal/Data/Stream/StreamD/Type.hs+19−19
design/optimization-guidelines.md+4
@@ -101,6 +101,10 @@ Step function of a stream or unfold:
101101 it is called. More states means more jumps and may affect code locality, and
102102 efficiency of low level code (e.g. register allocation) because of
103103 independent placement of the code blocks in different states.
104+
105+ In some cases we may have to go against the above guideline and introduce a
106+ separate state even though it is not necessary. See the GroupConsume state in
107+ foldMany for an example.
104108* Keep minimum possible data in state. More variables in state may lead
105109 to poor performance because the state may not fit into registers and the
106110 spill may cause allocations on each iteration of the loop. Mutable state
src/Streamly/Internal/Data/Stream/StreamD/Type.hs+19−19
@@ -588,6 +588,7 @@ take n (Stream step state) = n `seq` Stream step' (state, 0)
588588{-# ANN type GroupState Fuse #-}
589589data GroupState s fs b a
590590 = GroupStart s
591+ | GroupConsume s fs a
591592 | GroupBuffer s fs
592593 | GroupYield b (GroupState s fs b a)
593594 | GroupFinish
@@ -604,16 +605,17 @@ foldMany (Fold fstep initial extract) (Stream step state) =
604605 -- fs = fold state
605606 fs <- initial
606607 return $ Skip (GroupBuffer st fs)
608+ -- This state is not strictly required but it helps the compiler fuse the
609+ -- code.
610+ step' _ (GroupConsume st fs x) = do
611+ fs' <- fstep fs x
612+ case fs' of
613+ FL.Done b -> return $ Skip (GroupYield b (GroupStart st))
614+ FL.Partial ps -> return $ Skip (GroupBuffer st ps)
607615 step' gst (GroupBuffer st fs) = do
608616 r <- step (adaptState gst) st
609617 case r of
610− Yield x s -> do
611− res <- fstep fs x
612− return
613− $ Skip
614− $ case res of
615− FL.Done b -> GroupYield b (GroupStart s)
616− FL.Partial ps -> GroupBuffer s ps
618+ Yield x s -> return $ Skip $ GroupConsume s fs x
617619 Skip s -> return $ Skip (GroupBuffer s fs)
618620 Stop -> do
619621 b <- extract fs
@@ -628,26 +630,24 @@ foldMany1 (Fold fstep initial extract) (Stream step state) =
628630
629631 where
630632
631− {-# INLINE consume #-}
632− consume x s fs = do
633− res <- fstep fs x
634− return
635− $ Skip
636− $ case res of
637− FL.Done b -> GroupYield b (GroupStart s)
638− FL.Partial ps -> GroupBuffer s ps
639−
640633 {-# INLINE_LATE step' #-}
641634 step' gst (GroupStart st) = do
642635 r <- step (adaptState gst) st
643636 case r of
644− Yield x s -> initial >>= consume x s
637+ Yield x s -> do
638+ fi <- initial
639+ return $ Skip $ GroupConsume s fi x
645640 Skip s -> return $ Skip (GroupStart s)
646− Stop -> return Stop
641+ Stop -> return $ Stop
642+ step' _ (GroupConsume st fs x) = do
643+ fs' <- fstep fs x
644+ case fs' of
645+ FL.Done b -> return $ Skip (GroupYield b (GroupStart st))
646+ FL.Partial ps -> return $ Skip (GroupBuffer st ps)
647647 step' gst (GroupBuffer st fs) = do
648648 r <- step (adaptState gst) st
649649 case r of
650− Yield x s -> consume x s fs
650+ Yield x s -> return $ Skip $ GroupConsume s fs x
651651 Skip s -> return $ Skip (GroupBuffer s fs)
652652 Stop -> do
653653 b <- extract fs