如果在运行时替换函数,会 Clojure/JVM GC 旧代码吗?
If you replace functions at runtime, will Clojure/JVM GC old code?
如果经常在运行时替换函数,the way this poster wanted to do for the purposes of genetic-programming,会不会Clojure/JVM GC旧代码?
有疑问问电脑!我写了一个快速测试:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(defn create-fn
[n]
(let [fname (symbol (format "add-%d" n))
body (vector '[x] (list '+ n 'x))
fn-form (apply list 'clojure.core/defn fname body)
fn-ref (eval fn-form)]
fn-ref))
(defn create-and-call-fn
[n]
(let [fn-ref (create-fn n)
fn-result (fn-ref 3)]
(when-not (= (+ 3 n) fn-result)
(throw (ex-info "bad result" (vals->map n fn-result))))))
(dotest
(let [f5 (create-fn 5)
f5-result (f5 3)]
(is= 8 f5-result))
(dotimes [i 99999]
(when (zero? (mod i 100)) (spyx i))
(create-and-call-fn i)))
创建多达 10 万个函数后,它仍然有效。 YMMV!
以上是根据this template project.
答案是肯定的,生成的代码应该在将来的某个时候被收集。什么时候没有指定;它可能发生得晚,也可能永远不会发生。
另一件需要注意的事情是(特别是在使用来自另一个 eval 的代码时)是您在生成的代码中是否有循环引用以防止它们被卸载。通常,当一个 ClassLoader 被释放时,它的所有 classes 也会被释放——并且 JVM 之上的一些 interpreted/JITd 语言使用它来允许代码被回收。当 classes 被卸载时,任何编译的代码也会被丢弃——但是如果你有一个 class 的实例的引用 classloader (比如,在 ThreadLocalStorage 中)然后它将固定实例,然后是 class,然后是 classloader,所以它们可能仍然会泄漏。
如果经常在运行时替换函数,the way this poster wanted to do for the purposes of genetic-programming,会不会Clojure/JVM GC旧代码?
有疑问问电脑!我写了一个快速测试:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test))
(defn create-fn
[n]
(let [fname (symbol (format "add-%d" n))
body (vector '[x] (list '+ n 'x))
fn-form (apply list 'clojure.core/defn fname body)
fn-ref (eval fn-form)]
fn-ref))
(defn create-and-call-fn
[n]
(let [fn-ref (create-fn n)
fn-result (fn-ref 3)]
(when-not (= (+ 3 n) fn-result)
(throw (ex-info "bad result" (vals->map n fn-result))))))
(dotest
(let [f5 (create-fn 5)
f5-result (f5 3)]
(is= 8 f5-result))
(dotimes [i 99999]
(when (zero? (mod i 100)) (spyx i))
(create-and-call-fn i)))
创建多达 10 万个函数后,它仍然有效。 YMMV!
以上是根据this template project.
答案是肯定的,生成的代码应该在将来的某个时候被收集。什么时候没有指定;它可能发生得晚,也可能永远不会发生。
另一件需要注意的事情是(特别是在使用来自另一个 eval 的代码时)是您在生成的代码中是否有循环引用以防止它们被卸载。通常,当一个 ClassLoader 被释放时,它的所有 classes 也会被释放——并且 JVM 之上的一些 interpreted/JITd 语言使用它来允许代码被回收。当 classes 被卸载时,任何编译的代码也会被丢弃——但是如果你有一个 class 的实例的引用 classloader (比如,在 ThreadLocalStorage 中)然后它将固定实例,然后是 class,然后是 classloader,所以它们可能仍然会泄漏。