on master help sign in
update documentation for maxBuffer changes for ParallelT
commitfbb627da95ab654a3f73e03cd5cf2ed0ca26dd1c authorHarendra Kumar <harendra.kumar@gmail.com> dateFri 2 Aug 2019, 04:37 (7 years ago) parent196b4de
3 files changed+30−48
src/Streamly.hs+1−3 src/Streamly/Streams/Combinators.hs+2−1 src/Streamly/Streams/Parallel.hs+27−44
src/Streamly.hs+1−3
@@ -409,9 +409,7 @@ forEachWith = P.forEachWith
409409-- parameters to control the concurrency of the enclosed stream. A parameter
410410-- set at any point remains effective for any concurrent combinators used
411411-- downstream until it is reset. These control parameters have no effect on
412−-- non-concurrent combinators in the stream, or on non-concurrent streams. They
413−-- also do not affect 'Parallel' streams, as concurrency for 'Parallel' streams
414−-- is always unbounded.
412+-- non-concurrent combinators in the stream, or on non-concurrent streams.
415413
416414-- $adapters
417415--
src/Streamly/Streams/Combinators.hs+2−1
@@ -42,7 +42,8 @@ import Streamly.Streams.Serial (SerialT)
4242-- | Specify the maximum number of threads that can be spawned concurrently for
4343-- any concurrent combinator in a stream.
4444-- A value of 0 resets the thread limit to default, a negative value means
45−-- there is no limit. The default value is 1500.
45+-- there is no limit. The default value is 1500. 'maxThreads' does not affect
46+-- 'ParallelT' streams as they can use unbounded number of threads.
4647--
4748-- When the actions in a stream are IO bound, having blocking IO calls, this
4849-- option can be used to control the maximum number of in-flight IO requests.
src/Streamly/Streams/Parallel.hs+27−44
@@ -378,49 +378,30 @@ x |&. f = f |$. x
378378-- ParallelT
379379------------------------------------------------------------------------------
380380
381−-- | Async composition with simultaneous traversal of all streams.
382−--
383−-- The Semigroup instance of 'ParallelT' concurrently /merges/ two streams,
384−-- running both strictly concurrently and yielding elements from both streams
385−-- as they arrive. When multiple streams are combined using 'ParallelT' each
386−-- one is evaluated in its own thread and the results produced are presented in
387−-- the combined stream on a first come first serve basis.
388−--
389−-- 'AsyncT' and 'WAsyncT' are /concurrent lookahead streams/ each with a
390−-- specific type of consumption pattern (depth first or breadth first). Since
391−-- they are lookahead, they may introduce certain default latency in starting
392−-- more concurrent tasks for efficiency reasons or may put a default limitation
393−-- on the resource consumption (e.g. number of concurrent threads for
394−-- lookahead). If we look at the implementation detail, they both can share a
395−-- pool of worker threads to evaluate the streams in the desired pattern and at
396−-- the desired rate. However, 'ParallelT' uses a separate runtime thread to
397−-- evaluate each stream.
398−--
399−-- 'WAsyncT' is similar to 'ParallelT', as both of them evaluate the
400−-- constituent streams fairly in a round robin fashion.
401−-- However, the key difference is that 'WAsyncT' is lazy or pull driven
402−-- whereas 'ParallelT' is strict or push driven. 'ParallelT' immediately
403−-- starts concurrent evaluation of both the streams (in separate threads) and
404−-- later picks the results whereas 'WAsyncT' may wait for a certain latency
405−-- threshold before initiating concurrent evaluation of the next stream. The
406−-- concurrent scheduling of the next stream or the degree of concurrency is
407−-- driven by the feedback from the consumer. In case of 'ParallelT' each stream
408−-- is evaluated in a separate thread and results are /pushed/ to a shared
409−-- output buffer, the evaluation rate is controlled by blocking when the buffer
410−-- is full.
411−--
412−-- Concurrent lookahead streams are generally more efficient than
413−-- 'ParallelT' and can work pretty efficiently even for smaller tasks because
414−-- they do not necessarily use a separate thread for each task. So they should
415−-- be preferred over 'ParallelT' especially when efficiency is a concern and
416−-- simultaneous strict evaluation is not a requirement. 'ParallelT' is useful
417−-- for cases when the streams are required to be evaluated simultaneously
418−-- irrespective of how the consumer consumes them e.g. when we want to race
419−-- two tasks and want to start both strictly at the same time or if we have
420−-- timers in the parallel tasks and our results depend on the timers being
421−-- started at the same time. We can say that 'ParallelT' is almost the same
422−-- (modulo some implementation differences) as 'WAsyncT' when the latter is
423−-- used with unlimited lookahead and zero latency in initiating lookahead.
381+-- | Async composition with strict concurrent execution of all streams.
382+--
383+-- The 'Semigroup' instance of 'ParallelT' executes both the streams
384+-- concurrently without any delay or without waiting for the consumer demand
385+-- and /merges/ the results as they arrive. If the consumer does not consume
386+-- the results, they are buffered upto a configured maximum, controlled by the
387+-- 'maxBuffer' primitive. If the buffer becomes full the concurrent tasks will
388+-- block until there is space in the buffer.
389+--
390+-- Both 'WAsyncT' and 'ParallelT', evaluate the constituent streams fairly in a
391+-- round robin fashion. The key difference is that 'WAsyncT' might wait for the
392+-- consumer demand before it executes the tasks whereas 'ParallelT' starts
393+-- executing all the tasks immediately without waiting for the consumer demand.
394+-- For 'WAsyncT' the 'maxThreads' limit applies whereas for 'ParallelT' it does
395+-- not apply. In other words, 'WAsyncT' can be lazy whereas 'ParallelT' is
396+-- strict.
397+--
398+-- 'ParallelT' is useful for cases when the streams are required to be
399+-- evaluated simultaneously irrespective of how the consumer consumes them e.g.
400+-- when we want to race two tasks and want to start both strictly at the same
401+-- time or if we have timers in the parallel tasks and our results depend on
402+-- the timers being started at the same time. If we do not have such
403+-- requirements then 'AsyncT' or 'AheadT' are recommended as they can be more
404+-- efficient than 'ParallelT'.
424405--
425406-- @
426407-- main = ('toList' . 'parallely' $ (fromFoldable [1,2]) \<> (fromFoldable [3,4])) >>= print
@@ -462,7 +443,9 @@ x |&. f = f |$. x
462443-- Note that parallel composition can only combine a finite number of
463444-- streams as it needs to retain state for each unfinished stream.
464445--
465−-- @since 0.1.0
446+-- /Since: 0.7.0 (maxBuffer applies to ParallelT streams)/
447+--
448+-- /Since: 0.1.0/
466449newtype ParallelT m a = ParallelT {getParallelT :: Stream m a}
467450 deriving (MonadTrans)
468451