[英]Haskell streaming - how to separate 1 stream into 2 after copy?
[英]GroupBy of stream by agreggateId (Haskell / concurrency streaming)
上下文 :我正在CQRS中实现一个App,并且正在尝试优化命令的处理(基本上是通过汇总ID的1个流)...
问题 :我想拥有第一个流来接收所有命令,并通过它们的集合ID在不同线程上分派这些命令:
1)集合中的命令以串行方式处理
2)聚合独立(并行)处理其命令。
解决方案 :我试图基本上通过聚合ID在流上执行groupBy ...为了帮助一点,我将示例简化如下:
module Sandbox where
import Streamly
import qualified Streamly.Prelude as S
import Control.Concurrent
import Control.Monad.IO.Class (MonadIO(..))
main :: IO ()
main = do
runStream $ parallely $ S.fromList getAggregateIds |& S.mapM (\x -> do
threadId <- myThreadId
liftIO $ putStrLn $ (show threadId) ++ " value " ++ (show x))
getAggregateIds :: [Integer]
getAggregateIds = [1..3] <> [1..3]
因此此脚本显示以下结果:
ThreadId 17 value 1
ThreadId 15 value 2
ThreadId 19 value 3
ThreadId 13 value 1
ThreadId 16 value 3
ThreadId 18 value 2
我期望的是这样的事情(没有特殊的命令x总是在同一线程x1上进行处理):
ThreadId X1 value X
ThreadId Y1 value Y
ThreadId Z1 value Z
ThreadId X1 value X
ThreadId Y1 value Y
ThreadId Z1 value Z
谢谢 !!
在上面的代码中, parallely
决定为getAggregateIds
列表中的每个元素创建一个Haskell线程,该线程为[1,2,3,1,2,3]
。 parallely
并不关心列表中是否有重复的元素:它只是为每个元素启动一个线程。
原则上, parallely
只能分配少量的Haskell线程,以后再使用它们(可能是相同的ID或另一个ID),但这样做不会提高性能。 实际上,这里的关键部分是分配了Haskell线程,而不是OS线程,
Haskell线程非常轻巧,它们使用的内存很少,因此创建和处理它们的成本非常低廉。 尝试重用它们可能会导致性能下降。
此外,Haskell运行时可以在单个OS线程中执行许多Haskell线程。 通常,运行时会保留一小部分OS线程,并且Haskell线程会映射到这些线程。 由于OS线程不如轻量级OS线程确实在Haskell线程之间重用。
最后,请注意, ThreadId
是Haskell线程的名称,而不是OS的名称,因此正常情况下不会重复使用这些ID。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.