I ran some tests:

(defn domany [n s] (reduce (fn [a b] (assoc a :foo (.getClass b))) {}
(take n s)))

(def fnseq (iterate (fn [_] (fn [x] (+ 2 x))) 0))

(domany 10000000 fnseq)

With these, the last operation grinds away for a long time (a lot more
than 10x what it takes with only 1000000 iterations) and I suspect the
garbage collector is working hard (the Java process reaches the -Xmx
size and stays there) but it works.

But:

(def fnseq (iterate (eval '(fn [_] (fn [x] (+ 2 x)))) 0))

(domany 10000000 fnseq)

spews an OOME after a couple of minutes.

It looks like eval-generated functions, unlike closures, don't get
(completely) garbage collected if all references to them are dropped.
The message didn't actually say it ran out of permgen but it looks
like using eval as a run-time plugin loader or similarly has caveats,
but using ordinary closures a lot does not.

It would be unloading and reloading plugins on demand that would have
the caveat; loading plugins on demand but keeping them for session
lifetime thereafter won't leak permgen but letting plugins become
"garbage" and reloading them if needed again would leak permgen. It'd
be a tradeoff; I assume the partly-unloaded plugin would take up less
memory than a fully loaded one, but repeated reloads would chew up
more and more.

And loading identical code repeatedly still would leak, as the example
(which has a fixed s-expression as the argument to eval) shows.

Long story short: if you're going to dynamically load code at runtime,
and may want to load, discard, and load more constantly in a
long-running task, you'll need to write an interpreter unless/until
eval and/or Java's classloader mechanism are fixed so that
unreferenced eval-generated objects and/or dynamically-loaded Java
classes in general are fully garbage collectable.

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to