如何在 Haskell 的 TChan 上的生产者/消费者情况下限制生产者?

2024-02-18

我们有一些东西在 TChan 上倾销值,然后由消费者处理这些值。但消费者无法跟上,因此当生产者在通道上倾倒大量内容时,我们会使用大量内存,但消费者却无法跟上。如果通道队列达到一定大小或某种程度,是否有一种直接的方法让生产者阻塞,以便我们可以让生产者等待消费者赶上?


就像约翰的回答一样,我建议自己构建一个有界的 TChan。我的代码有所不同,因为它:

  1. 添加抽象(使得BTChan an ADT)
  2. 由于读取 IO 中的当前大小,消除了极端情况。
  3. 读取时尽量不要在 TVar 大小中构建 thunk(写入时不太重要,因为 thunk 只能是“一层深”——下一个操作总是需要评估大小)。
  4. 现在正在破解:http://hackage.haskell.org/package/bounded-tchan http://hackage.haskell.org/package/bounded-tchan

注意:老实说,如果我是你,我会忽略所有这些答案,只使用他的评论中链接的代码(除非它是糟糕的代码)。我敢打赌它的作用与我在这里所做的相同,但经过更多思考。

{-# LANGUAGE BangPatterns #-}
module BTChan
        ( BTChan
        , newBTChanIO
        , newBTChan
        , writeBTChan
        , readBTChan
        ) where

import Control.Concurrent.STM

data BTChan a = BTChan {-# UNPACK #-} !Int (TChan a) (TVar  Int)

-- | `newBTChan m` make a new bounded TChan of max size `m`
newBTChanIO :: Int -> IO (BTChan a)
newBTChanIO m = do
    szTV <- newTVarIO 0
    c    <- newTChanIO
    return (BTChan m c szTV)

newBTChan :: Int -> STM (BTChan a)
newBTChan m 
        | m < 1 = error "BTChan's can not have a maximum <= 0!"
        | otherwise = do
        szTV <- newTVar 0
        c    <- newTChan
        return (BTChan m c szTV)

writeBTChan :: BTChan a -> a -> STM ()
writeBTChan (BTChan mx c szTV) x = do
        sz <- readTVar szTV
        if sz >= mx then retry else writeTVar szTV (sz + 1) >> writeTChan c x

readBTChan :: BTChan a -> STM a
readBTChan (BTChan _ c szTV) = do
        x <- readTChan c
        sz <- readTVar szTV
        let !sz' = sz - 1
        writeTVar szTV sz'
        return x

sizeOfBTChan :: BTChan a -> STM Int
sizeOfBTChan (BTChan _ _ sTV) = readTVar sTV

STM 程序员需要注意的一些事项:

  • 显式调用retry将产生,将你的 haskell 线程置于阻塞状态,等待其中之一的状态TVar or TChan进行更改以便可以重试。这是避免检查值的方法IO并使用yield功能。
  • 与 MVar 一样,TVar 可以引用 thunk,这通常不是您想要的。也许有人应该制作一个 hackage 包来定义STVar, STChan, SBTChan and BTChan(严格和/或有界的 TVar 和 TChan)。
  • 实际上有必要写newBTChanIO而不是杠杆newBTChan因为的实现new{TVar,TChan}IO即使在以下情况下也能工作unsafePerformIO, which atomically不会。

编辑:通过将 TVar 分为一个供读者使用,一个供作者使用,从而减少争用,您实际上可以获得 2-5 倍的性能提升(取决于您使用的边界)。使用标准进行验证。改进版本 0.2.1 已经在 hackage 中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Haskell 的 TChan 上的生产者/消费者情况下限制生产者? 的相关文章

随机推荐

  • 使用 XML 代替 HTML 创建网页有哪些优点?

    有时 我会看到内容仅用 XML 而不是 HTML 或 XHTML 编写的网页 这些页面通常附加一些样式表 XSLT 或 CSS 这使得它们看起来像任何其他普通网页 我的问题是 这种方法有什么优点 如果有的话 为什么有人会选择这种方式 EDI
  • 如何使用 mysqldump 保存 UTF8mb4 数据?

    我正在使用 mysqldump 转储包含带有 UTF8MB4 数据的 UTF8MB4 列的数据库 当我导入这个 sql文件导入到支持 UTF8MB4 的新数据库中 所有 UTF8MB4 字符都会转换为 有人知道如何使 MySQL 和导入与
  • 如何使用 ffmpeg 从 YUV 视频中提取帧(或特定帧)

    这是从a中提取帧的代码MP4视频 ffmpeg i above marathon 250 mp4 images 03d bmp但相同的代码不适用于YUV格式化视频 有谁知道如何从中提取帧YUV格式化视频 它不起作用 因为 yuv 文件没有标
  • SVG矢量图形可以转换为PNG文件格式以便在Fireworks中使用吗?

    众所周知 有很多网站出售免版税图形 有些网站出售矢量图形 svg 或为您提供下载矢量图形的选项 我没有支持 SVG 的图形编辑器 目前 我正在使用旧版本的 Fireworks 我无法打开 SVG 文件类型 我也买不起 PhotoShop 或
  • 使用 WebClient 和 WebRequest 之间的编码差异?

    在获取一些随机的西班牙报纸索引时 我没有使用 WebRequest 正确获取变音符号 它们产生了这个奇怪的字符 同时使用 a 从同一个 uri 下载响应WebClient我得到了适当的回应 为什么会出现这种差异化呢 var client n
  • 通过调整浏览器大小来缩放 KineticJS Stage?

    最近发现了 KineticJS 因为我一直在尝试将我的 Flash 技能转换为 HTML Canvas 这是一个非常令人印象深刻的工具 问题 如果我使用像 Bootstrap 这样的前端 并且我有一个页面 其中包含几个包含 KineticJ
  • 在排序函数中处理 nils

    我不知道如何处理nils我的排序函数得到了 当我检查这个时 table sort一些电话后崩溃 if a nil then return false elseif b nil then return true end 出现此错误 用于排序的
  • SailsJS 中的 API 版本控制

    基于这个问题 我已经禁用了嵌套控制器和蓝图 我的问题是这样的 API 控制器 v1 UserController js 路线 js POST v1 user register v1 UserController createUser 策略
  • 在 Javascript for 循环声明中声明 var

    我确定我已经阅读过有关此问题的讨论 但找不到 简而言之 在循环声明内声明 for 循环的增量是否有缺点 这有什么区别 function foo for var i 0 i lt 7 i code 和这个 function foo var i
  • 如何模拟图像上传到Google App Engine Blobstore

    我正在使用 create upload url 将图像上传到 GAE blobstore uploadURL blobstore create upload url upload 为了对gae代码进行单元测试 您可以模拟图像上传吗 或者我应
  • Ehcache 与静态地图缓存实现

    我有几个表 其中的条目很少 并且它们永远不会动态更改 所以我想将整个表缓存在内存中以减少数据库的负载 我可以通过静态地图并将地图填充到静态块中轻松实现这一点 我想知道 Ehcache hibernate 是否可以以更有效的方式实现同 样的功
  • 在 data.table 中多次使用 :=

    我经常发现自己使用以下方法进行一长串链式计算 在同一个数据表上 例如 像这样的东西 test data table 1 10 1 10 1 10 1 10 test V1 V1 2 test V2 V1 V2 test V3 V2 V3 t
  • 使用 jQuery / AJAX 解码 JSON

    我正在尝试使用 jQuery 解码 JSON 这是我得到的结果 例如一个班级 这里有一个学生 Students Name John Grade 17 TotalClass 17 TotalCount 1 这就是我所做的 j ajax typ
  • 哪些 Web 框架和语言的开发时间最短?

    我正在尝试将一些网络开发想法付诸实践 不幸的是 我将是唯一的开发人员 因此我专注于获得一个良好的可调试 可测试的设置 以便我可以快速开发应用程序 您会推荐哪些语言 开发风格和框架来实现快速开发 上次我检查 RoR 是下一件大事 但那是很久以
  • 无法单独构建 Flutter Web 和 Flutter Mobile 应用

    我正在构建一个 flutter 项目 并且在将 Web 和移动代码集成到单个项目中时遇到问题 我想在我的移动代码中使用 Moor 和 Moor FFI 但即使我的 web main dart 和移动代码 main dev dart 的入口点
  • 使用 Flask-Session 扩展在 Flask 会话中未设置密钥

    现在我正在使用 Flask 第三方库Flask 会话 https flask session readthedocs io en latest 我没有运气让会议正常进行 当我连接到我的网站时 出现以下错误 运行时错误 会话不可用 因为没有密
  • 是否可以使用迭代器将向量分成 10 个组?

    I have let my vec 0 25 collect
  • g++版本兼容性

    这是一个特定的海湾合作委员会相关问题 我有一个用 g 4 1 2 编译的库 我想提供给用户 用户可以在他们的代码中使用我们的 API 并链接我们的库来创建最终的可执行文件 我的问题与 g 版本兼容性有关 我们的一些用户使用 g 4 4 3
  • 如何在同一域中托管我的 API 和 Web 应用程序?

    我有一个Rails API 和一个Web 应用程序 使用express 彼此完全分开且独立 我想知道的是 我必须单独部署它们吗 如果我这样做 我怎样才能使我的 api 处于mysite com api和网络应用程序mysite com 我见
  • 如何在 Haskell 的 TChan 上的生产者/消费者情况下限制生产者?

    我们有一些东西在 TChan 上倾销值 然后由消费者处理这些值 但消费者无法跟上 因此当生产者在通道上倾倒大量内容时 我们会使用大量内存 但消费者却无法跟上 如果通道队列达到一定大小或某种程度 是否有一种直接的方法让生产者阻塞 以便我们可以