繁体   English   中英

通过agreggateId通过流进行分组(Haskell /并发流)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM