on master help sign in
Use a recursive local loop inside step function

Though now, the loop does not fuse and earlier it fused completely. The fused loop is much more inefficient. Improves the performance by 3x, possibly due to less amount of state being threaded around the loop.

commit924d78e8e657f0212dbfe2aa2af9000eed3381c4 authorHarendra Kumar <harendra@composewell.com> dateWed 28 Oct 2020, 00:44 (6 years ago) parenta2a589e
1 file changed+21−30
src/Streamly/Internal/Data/Stream/StreamD.hs+21−30
src/Streamly/Internal/Data/Stream/StreamD.hs+21−30
@@ -1791,19 +1791,15 @@ data SplitOnState fs s a b w rb rh ck =
17911791 GO_START
17921792 | GO_EMPTY_PAT s
17931793 | GO_EMPTY_PAT_WITH s a
1794− -- | GO_SINGLE_PAT_BEGIN s a -- Only for splitSuffixOn
17951794 | GO_SINGLE_PAT_NEXT !fs s a
17961795 | GO_SINGLE_PAT_WITH !fs s a a
17971796 | GO_SHORT_PAT_ACCUM Int s !w
17981797 | GO_SHORT_PAT_NEXT !fs s !w
17991798 | GO_SHORT_PAT_NEXT_WITH !fs s a !w
18001799 | GO_SHORT_PAT_DRAIN Int !fs !w
1801− -- | GO_SHORT_PAT_YIELD_SEP Int !fs s w -- Only for splitSuffixOn.
18021800 | GO_KARP_RABIN_ACCUM Int s rb !rh
18031801 | GO_KARP_RABIN_NEXT !fs s rb !rh !ck
1804− | GO_KARP_RABIN_NEXT_WITH !fs s a rb !rh !ck
18051802 | GO_KARP_RABIN_DRAIN Int !fs rb !rh
1806− -- | GO_KARP_RABIN_YIELD_SEP Int !fs s rb rh -- Only for splitSuffixOn.
18071803 | GO_YIELD b (SplitOnState fs s a b w rb rh ck)
18081804 | GO_DONE
18091805
@@ -2010,32 +2006,27 @@ splitOn patArr (Fold fstep initial done) (Stream step state) =
20102006 else do
20112007 r <- done ini
20122008 return $ Skip $ GO_YIELD r GO_DONE
2013− -- XXX Theoretically this code can do 4 times faster if GHC generates
2014− -- optimal code. If we use just "(cksum1 == patHash)" condition it goes 4x
2015− -- faster, as soon as we add the "RB.unsafeEqArray rb v" condition the
2016− -- generated code changes drastically and becomes 4x slower. Need to
2017− -- investigate what is going on with GHC.
2018− stepOuter _ (GO_KARP_RABIN_NEXT_WITH fs s x rb rh cksum) = do
2019− old <- liftIO $ peek rh
2020− let cksum1 = deltaCksum cksum old x
2021− fres <- fstep fs old
2022− if (cksum1 == patHash)
2023− then do
2024− r <- done fres
2025− -- XXX It does not matter whether we give rh or rh1
2026− -- here. We restart anyway.
2027− return $ Skip $ GO_YIELD r $ GO_KARP_RABIN_ACCUM 0 s rb rh
2028− else do
2029− rh1 <- liftIO (RB.unsafeInsert rb rh x)
2030− return $ Skip $ GO_KARP_RABIN_NEXT fres s rb rh1 cksum1
2031− stepOuter gst (GO_KARP_RABIN_NEXT fs st rb rh cksum) = do
2032− res <- step (adaptState gst) st
2033− return
2034− $ Skip
2035− $ case res of
2036− Yield x s -> GO_KARP_RABIN_NEXT_WITH fs s x rb rh cksum
2037− Skip s -> GO_KARP_RABIN_NEXT fs s rb rh cksum
2038− Stop -> GO_KARP_RABIN_DRAIN patLen fs rb rh
2009+ stepOuter gst (GO_KARP_RABIN_NEXT fs0 st0 rb rh0 cksum0) =
2010+ go SPEC fs0 st0 rh0 cksum0
2011+
2012+ where
2013+
2014+ go !_ !fs !st !rh !cksum = do
2015+ res <- step (adaptState gst) st
2016+ case res of
2017+ Yield x s -> do
2018+ old <- liftIO $ peek rh
2019+ let cksum1 = deltaCksum cksum old x
2020+ fres <- fstep fs old
2021+ if (cksum1 == patHash)
2022+ then do
2023+ r <- done fres
2024+ return $ Skip $ GO_YIELD r $ GO_KARP_RABIN_ACCUM 0 s rb rh
2025+ else do
2026+ rh1 <- liftIO (RB.unsafeInsert rb rh x)
2027+ go SPEC fres s rh1 cksum1
2028+ Skip s -> go SPEC fs s rh cksum
2029+ Stop -> return $ Skip $ GO_KARP_RABIN_DRAIN patLen fs rb rh
20392030 stepOuter _ (GO_KARP_RABIN_DRAIN 0 fs _ _) = do
20402031 r <- done fs
20412032 return $ Skip $ GO_YIELD r GO_DONE