簡體   English   中英

流媒體庫中的慣用預取

[英]Idiomatic prefetching in a streaming library

我正在使用流媒體庫,但會接受使用管道或管道的答案。

說我有

import Streaming (Stream, Of)
import qualified Streaming.Prelude as S

streamChunks :: Int -> Stream (Of Thing) IO ()
streamChunks lastID = do
  flip fix 0 $ \go thingID ->
    unless (thingID > lastID) $ do
      thing <- highLatencyGet thingID
      S.yield thing
      go (thingID+1)

為了減少等待時間,我想叉highLatencyGet檢索下一個Thing與處理先前平行Thing在消費。

顯然,我可以將我的函數轉換為創建一個新的MVar並在調用yield等之前分配下一批。

但我想知道是否有一種慣用的(可組合的)方法來做到這一點,這樣它就可以打包在一個庫中,並且可以在任意IO Stream上使用。 理想情況下,我們也可以配置預取值,例如:

prefetching :: Int -> Stream (Of a) IO () -> Stream (Of a) IO ()

此解決方案使用管道,但它可以很容易地適應使用流媒體 確切地說,它需要管道管道 - 並發異步包。

它不能以“直接”的方式工作。 它不僅僅是簡單地轉換Producer ,還需要一個消耗Producer的“折疊功能”。 這種延續傳遞方式對於設置和拆除並發機制是必要的。

import Pipes
import Pipes.Concurrent (spawn',bounded,fromInput,toOutput,atomically)
import Control.Concurrent.Async (Concurrently(..))
import Control.Exception (finally)

prefetching :: Int -> Producer a IO () -> (Producer a IO () -> IO r) -> IO r
prefetching bufsize source foldfunc = do
    (outbox,inbox,seal) <- spawn' (bounded bufsize)
    let cutcord effect = effect `finally` atomically seal
    runConcurrently $
        Concurrently (cutcord (runEffect (source >-> toOutput outbox)))
        *>
        Concurrently (cutcord (foldfunc (fromInput inbox)))

原始生產者的輸出被重定向到有界隊列。 同時,我們將producer-folding函數應用於從隊列中讀取的生產者。

每當並發操作完成時,我們會小心地立即關閉通道以避免另一側懸空。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM