2024年Clojure状态调查!中分享您的看法。

欢迎!有关如何工作的更多信息,请参阅关于页面。

0
core.async

目前,core.async使用的线程池被定义为全局的,它们在各自的线程池中由所有Go或线程宏共享。

请参阅:https://github.com/clojure/core.async/blob/ac0f1bfb40237a18dc0f03c0db5df41657cd23a6/src/main/clojure/clojure/core/async.clj#L391-L411
https://github.com/clojure/core.async/blob/ac0f1bfb40237a18dc0f03c0db5df41657cd23a6/src/main/clojure/clojure/core/async/impl/dispatch.clj#L16

对此有更多控制将是非常有用的,希望不要通过简单的setter来实现,就像我们在core中为agents(set-agent-send-executor!)所做的那样,因为它一次只允许使用一个线程池。
一个可能的解决方案是通过thread-call的选项映射参数来执行此操作,以及/或为Go块提供其他机制(使用相同签名的go-call)。将此参数作为映射也会允许在必要时进一步扩展内部组件,而无需对API进行重大更改。

12 条回答

0

评论由:mpenet

我在这里有一个补丁https://github.com/mpenet/core.async/commit/1c2b0a9af9a5e891af0f1631b8debd337a73999d,其中添加了此功能。

它增加了两个宏:go*和thread**。它们与go(thread)相同,但首先需要一个选项映射,然后是主体。选项映射可以接收一个具有clojure.core.async.impl.protocols/Executor实现的:executor键。

我将thread执行器移动到了与ioc/go相同的命名空间,并支持相同的接口,而不是使用原始的j.u.c Executor实例。现在,此命名空间中声明的两个实例都是延迟的(在延迟块中),这防止了无用的线程池初始化/泄漏。

最后,我还修改了线程调用以支持相同的选项映射。

我很快会将.patch文件附加到问题单上。

0

评论由:mpenet

实际上,这个补丁是不完整的,我刚刚发现ioc-macros的重新写入会导致对全局线程池的调用(尤其是通过put(image: , take)回调)。

我们可以在创建通道时传递一个执行器,这样就可以相对容易地强制ops在这个通道上运行(部分示例在这里 https://github.com/mpenet/core.async/commit/1449b3842052033cdf917ae92259ad9789722fdb)。

我相信这也是manifold处理它的方式,但到此为止可能还有更多未知之处。

0

评论由:mpenet

包含chan修改的补丁。现在chan可以接受一个额外的参数,该参数将会是一个clojure.core.async.impl.protocols/Executor兼容的执行器,在提供该执行器的情况下,将使用该执行器而不是全局默认池。

0

评论由:mpenet

以单一提交提供补丁(更易于阅读)。您还可以在此处查看更改:https://github.com/mpenet/core.async/commit/e7dea04553935863d1abb1880d84bbdc273854ec

0

评论者:gshayban

嗨,Max。我认为需要更好地控制这一点。

基本上有两个需求
1) 回调需要唤醒暂停的go-blocks。
2) 运行更重的thread(这可能会阻塞,因此不能使用同一池)

目前通道回调不知道它们唤醒了什么。我认为这是一个良好的设计。如果它们唤醒了一个线程,那么只是通过传递一个promise(链接:1)间接地这样做
我相信不应该在channels.clj中提及特定的执行器。在多个不同位置运行go-blocks可能是一个反模式,因为go-blocks不应该阻塞或执行I/O。

但我非常欢迎对thread块执行器的控制。

(链接:1) https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L137

0

评论由:mpenet

你好 Ghadi,

感谢你的反馈,但我不认为你正确地阅读了我的补丁。

我没有改变你提到的案例(承诺),唯一改变的是,对于调用clojure.core.async.impl.dispatch/run function的少数情况,意味着该函数在全局定义的threadpool中运行,除了thread以外,所有core.async实现都在这个threadpool中运行,现在可以选择通过提供的threadpool function来完成。默认设置没有改变,如果你不传递executor,你将得到当前无任何变化的core.async行为。

有一些人提到了这种需求,无论是公开的还是私下的,包括我自己,我还知道有一个团队表达过相同的关注并已经将他们的系统从core.async切换到manifold,因为后者提供了更多的这种类型的旋钮。

最终这关乎控制,如果你不关心它,对core.async及其当前的执行模型不会产生任何影响,但对于需要这类细致调节的人来说,这是非常重要的。

几天前这个话题又在twitter上出现了: https://twitter.com/puredanger/status/576378306062262272,你肯定也可以在irc日志中找到相关讨论。

如果可能的话,我会将其作为一个库发布,但由于有关代码有时非常深植,而不修改整个库就几乎是无法做到的,因此有了这个补丁。

0

评论由:mpenet

与上一个补丁相同,为promise-chan添加了缺失的arity。

0

评论者:stu

将我的点赞视为对问题而非此处采用的方法的赞同。

对我来说,go和thread是两个要分别考虑的不同案例。我不清楚为什么chan需要考虑,而且我不想阅读补丁(或学习有关impl命名空间)来了解原因。有人可以解释不用参考实现方式的chan的案例吗?

关于这个问题有在开发者列表上的讨论吗?

0

评论由:mpenet

当然,只要这个得到了改进/修复。

如果你读过补丁或者channel的源码,你就会看到
这些通道在线程池上运行其回调。

当我提交这个补丁时,我在IRC上花费了一些时间与Timothy Baldridge讨论它,并按照他的建议做了一些修改。
鉴于你可能与他在同一个办公室,我建议你与他讨论当前的方法,因为他比我更熟悉代码库。

由lxsameer评论:
嘿,朋友们,

0
我向threadpool ns添加了几个函数,以便用户可以为主线程池和thread宏提供执行器。

目前这只是个草案,我想知道其他人对它的看法,然后再花更多时间在上面。请查看我在以下仓库中的提交:

https://github.com/Codamic/core.async/commit/5cfa3ac34f963dc67329722149d041629a6c6e6f

它应该能给你一些启示。期待您的意见。

问候

0

评论由:mpenet

0
...