请在 2024 年 Clojure 状态调查 中分享您的想法!

欢迎!请参阅 关于 页以获取更多关于此如何工作的信息。

0
语法和读取器
已关闭

最小化例子

`
(fn foo [x]
(if true

(^:once fn* []
 ;; x is not cleared here
 x)))

`

这意味着 Clojure 编译器将每个在循环或 try/catch 表达式内部使用的局部引用内部提升到 FNONCE,在条件分支中,现在无法清除。

作为一个具体示例,如 Slack 中报道的,

`
;; 这导致 OOM
(defn test1 [x]
(if true

(do
  (try (doseq [_ x] _))
  1)
0))

(test1 (take 1000000 (range)))

;; 这不会导致 OOM
(defn test2 [x]
(do

(try (doseq [_ x] _))
1))

(test2 (take 1000000 (range)))

`

方法:如果函数为 ^:once 并且存在一个现有的清除帧,则不要设置一个新的清除帧
补丁:0001-CLJ-2145-fix-clearing-of-locals-closed-over-by-a-FNO.patch

注释已关闭: 已修复在 Clojure 1.12.0-rc1 和 1.11.4 中

1 答案

0
参考: https://clojure.atlassian.net/browse/CLJ-2145 (由 bronsa 提出)
...