2024 Clojure 状态调查! 分享您的想法。

欢迎!为了了解更多关于这个平台的信息,请参阅关于 页。

0
core.async

当前,在现代化的浏览器中,(<! (timeout 0)) 将花费大约 4ms,因为最终它会被转换为 (js/setTimeout f 0)。在现代化浏览器中,即使给 0,setTimeout 也不会在 4ms 内返回。如果你只想将控制权最小时间地交给浏览器,那么 4ms 时间太长了。

查看
https://github.com/clojure/core.async/blob/d073896192fa55fab992eb4c9ea57b86ec5cf076/src/main/clojure/cljs/core/async/impl/timers.cljs#L161-L164

然后是
https://github.com/clojure/core.async/blob/d073896192fa55fab992eb4c9ea57b86ec5cf076/src/main/clojure/cljs/core/async/impl/dispatch.cljs#L35-L36

我正在想对这个小的重写进行修改

(defn queue-delay (link: f delay)
(if (= 0 delay)

  (goog.async.nextTick f)      ;;  <---- new path for 0
 (js/setTimeout f delay))      ;;  <---- existing path

11 条答案

0

由 pkobrien 发布的评论

我认为使用goog.Timer.callOnce对于任何时间长度都应该是有效的,并且仍将解决由使用js/setTimeout引起的问题。

0

由 mikethompson 发布的评论

从我看到的来看,goog.Timer.callOnce 使用 setTimeout。但是那正是我们试图在 0ms 持续时间内避免的事情。因此,我不认为 callOnce 是一个解决方案。

0

由 pkobrien 发布的评论

我认为你是正确的,迈克。尽管难以置信,但显然谷歌知道这个问题。但当我重新阅读goog.Timer代码时,我看不到他们在这里修复了它。看起来goog.async.nextTick是唯一的解决方案。

0

由 pkobrien 发布的评论

我只想提到这个问题是针对ClojureScript版本的core.async,并且看起来使用(<! (timeout 0))作为暂时将控制权Returning回js事件处理的方式是一种相当规范的用法。所以我认为这一点非常关键,需要让它更加高效。

0

评论者:gshayban

阅读这个“错误”时,感觉实际问题是CLJS中goblock分派更多样化。它应该得到改进,但让(<! (timeout 0))——这种无意义的代码——表现得不同并不能以有意义的方式解决问题。

我们应该从根本消除这个黑客软件的需要,而不是使未定义的行为更加具体。ASYNC-131和ASYNC-43是相关的,也许更好的起点。

0

由 mikethompson 发布的评论

@Ghadi
1. 我看不出问题131如何紧密相关到可以作为“更好的起点”。它有不同的重点,代表了不同的需求,并且可能会有不同的解决方案(正如当前的建议所证实的那样)。

  1. 这几乎看起来Issue 43可能会随着大卫·诺伦(David Nolen)提到的Google Closure分派的转换而关闭。顺便说一下,你会注意到我的建议确实是使用goog.async.nextTick(因此我坚持Google Closure方法)。

此外,我不同意你的观点,即(<! (timeout 0))是“无意义的代码”。在单线程环境中,如浏览器,有时需要从go循环(如果该go循环暂时占用CPU)中显式地将控制权“归还”给浏览器。目前,(<! (timeout 0))是唯一我知道的方法。它可以重构为(<! (yield-cpu))以使意图更清晰,这可能是很好,但我想拥有的一种方式是将CPU释放出去,而不会总是花费4ms。我相信这种需求是真实的,而且非常“有意义”:-)

0

由 mikethompson 发布的评论

@Ghadi
为了清晰起见...你将其称为“bug”,并用引号括起来。几乎就好像它不是bug。

但对我来说,这是一个足够真实的“bug”,我必须要么与分支(fork)一起工作,要么完全放弃使用core.async。

我需要 (<! (timeout 0)) 表示0,或者尽可能接近0。我需要它按照广告工作。当前的实现并没有实现0(或尽可能接近0),而是提供了(<! (timeout 4))的相同结果,4ms与0ms(或尽可能接近0)相比是漫长的。每次循环4ms,goloop只能每秒迭代250次。

任何有一个在监听动态webSocket输出的goloop的人都会遇到这个问题。他们需要疯狂地处理(没有4ms延迟),但是还需要将控制权交回浏览器,这样浏览器就可以不时地做它需要做的事情。所有这些都因为浏览器页面失去“关注”,进入后台,js节流,动画帧变慢等问题而加剧。

0

由 pkobrien 发布的评论

如果你在阅读这篇文档,以下是我开始使用的一个临时解决方案

`
(defn yield [])
(let [ch (chan)]

(goog.async.nextTick #(close! ch))
ch))

(go
; 一些代码...
(<! (yield)) ;; 用 (<! (timeout 0)) 替换
...)
`

0

由 mikethompson 发布的评论

这很好!当然提供了一个占位符解决方案。

0

由 mikethompson 发布的评论

在与halgari进一步讨论后,我相信这个应该关闭为“不会修复”。

https://www.reddit.com/r/Clojure/comments/5aprn3/in_coreasync_using_timeout_with_0_delay_causes_a/

0
参考:https://clojure.atlassian.net/browse/ASYNC-137 (由mikethompson报告)
...