Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move IsStream type class definition out of the low level StreamK module #1223

Merged
merged 6 commits into from
Sep 14, 2021

Conversation

harendra-kumar
Copy link
Member

Description

Move IsStream definition out of the low level StreamK module and push it up in a higher level IsStream/Type module. This is a step towards creating a streamly-core package devoid of any non-boot library dependencies, as mentioned in #533 . Also, this will facilitate moving to monomorphic stream types and modules in future, currently we use polymorphic streams based on IsStream type class.

The IsStream type class contains MonadAsync type in the consM method. This refactor allows lifting MonadAsync, therefore, dependency on monad-control out of the low level modules.

The main changes are in StreamK/Type.hs, StreamK.hs, IsStream/Type.hs, Stream/Serial.hs, the rest of the changes are mostly a fallout of these changes. Need to review these files and a few other files with important changes, the rest of the changes can be glanced over.

Things to check

  • Performance remains the same
  • Documentation is not lost
  • Exposed APIs do not change - cabal-diff
  • Concurrent APIs remain concurrent

Performance Notes

The foldrS benchmark has regressed by around 100 times, but the original perf numbers were good because of
a trivial foldr/build fusion. If we see foldrSMap which actually performs a map
using foldrS then it has improved by 2x.

Benchmark  default(0)(ns) default(1)(ns)
All.Prelude.Serial/o-1-space.mapping.foldrS 37636.90 3002730.00
All.Prelude.Serial/o-1-space.mapping.foldrSMap 6872930.00 2895490.00

iterateState benchmark now requires a SPECIALIZE pragma to specialize.

Other degradations, but the core looks the same for all these cases, may want to verify once again:

ParserD.serialWith 50% degradation, many
Parser serialWith/split_ 50%
Array.Foreign writeN/writeLastN/fromList 50% deg

Other than these there are no significant regressions, there are many improvements though.

-- continuation and a yield continuation.
{-# INLINE_EARLY mkStream #-}
mkStream :: IsStream t
=> (forall r. State K.Stream m a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember there being an issue or a comment about fixing K.Stream in State. No comment. Just stating it here.

{-# INLINE_LATE drain #-}
drain :: Monad m => Stream m a -> m ()
-- drain = foldrM (\_ xs -> xs) (return ())
drain (Stream step state) = go SPEC state
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this removed/moved?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is required in low level modules like instances of SerialT and other types.

@@ -471,7 +480,7 @@ sourceConcatMapId val n =
{-# INLINE concatMapBySerial #-}
concatMapBySerial :: Int -> Int -> Int -> IO ()
concatMapBySerial outer inner n =
S.drain $ S.concatMapBy S.serial
S.drain $ S.concatMapWith S.serial
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are concatMapWith and concatMapBy same?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

concatMapBy is older name, later renamed to concatMapWith.

Copy link
Member

@adithyaov adithyaov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went through them. Looks good. Did you tally and make sure you've not removed any API by mistake? You're using some tool I believe.

@harendra-kumar
Copy link
Member Author

cabal-diff is the tool. There is one change to the exposed API, I will fix that. There are several changes to Internal APIs. I am attaching the diff.

API diff of master with 0.8.0

bin/test.sh Outdated
--cabal-build-options) shift; CABAL_BUILD_OPTIONS+=$1; shift ;;
--hpc-report-options) shift; HPC_REPORT_OPTIONS=$1; shift ;;
--rtsopts) shift; RTS_OPTIONS=$1; shift ;;
--cabal-build-options) shift; CABAL_BUILD_OPTIONS+=" $1"; shift ;;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fixed this in another change. I'll undo that.

@harendra-kumar
Copy link
Member Author

I am going to squash and merge it.

The IsStream type class contains MonadAsync type in the consM method.
This refactor allows lifting MonadAsync, therefore, dependency on
monad-control out of the low level modules.
To include tests that require large amounts of RAM
@harendra-kumar harendra-kumar merged commit f6b88dc into master Sep 14, 2021
@harendra-kumar harendra-kumar deleted the streamly-core branch September 15, 2021 13:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants