![](/img/trans.png)
[英]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.