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

欢迎!请查看关于页面以了解更多关于如何使用本网站的信息。

0
core.async

运行此代码最终会抛出OOME

`
(let [c (a/chan)]
(a/go (while (a/<! c)))
(a/go

(when-some [xs (range)]
  (doseq [x xs]
    (a/>! c x)))))

`

这个(用{{let}}而不是{{when-some}})可以正常工作

`
(let [c (a/chan)]
(a/go (while (a/<! c)))
(a/go

(let [xs (range)]
  (doseq [x xs]
    (a/>! c x)))))

`

在前一个例子中,range序列存储在堆上(在go块的状态数组中),并且在doseq迭代期间一直保留,尽管在循环初始化后不再需要。
在后者中,range序列存储在栈上,因此编译器能够执行其局部清理魔术。

这种行为很可能会发生在每个跨越多个SSA块的值上。

3 个答案

0

由 alexmiller发表的评论:

问题的实质不是when-some实际上是一个let,而你却在let中持有无限范围的头部吗?

0

由 leonoel发表的评论:

我已经用更少的虚构示例更新了描述。
问题发生的原因在于一个let绑定包围了一个控制流表达式。这实际上将值从栈移动到堆上,阻止编译器清除引用。

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