-
-
Notifications
You must be signed in to change notification settings - Fork 180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Classes loaded by Pods are leaked #268
Comments
Hey @stephenbrady thanks for the report! How exactly did you detect this memory leak? Did you get |
Sure. By profiling in jvisualvm. I can see with each invocation of This is with jdk8, so no perm gem memory issues. |
@stephenbrady Thanks, that confirms my understanding. |
I read that page but assumed that Boot does not use/depend on core.async and searching for classes in the YourKit classbrowser doesn't list any classes containing "async". The program I use for testing also is very minimal and does not load any additional deps: #!/usr/bin/env boot
(require '[boot.pod :as pod])
(defn -main [& args]
(loop [i 0]
(let [c-pod (pod/make-pod (get-env))]
(boot.util/info "New pod taken: %s\n" c-pod)
(pod/with-eval-in c-pod
(boot.util/info "Hi from pod no. %s.\n" ~i))
(pod/destroy-pod c-pod)
(recur (inc i))))) Used with these
|
I believe I have figured out what is causing this - I believe boot is Code that triggers either The following test case demonstrates that, and runs indefinitely for #!/usr/bin/env boot
(require '[boot.pod :as pod])
(defn -main [& args]
(loop [i 0]
(doto
(Thread.
#(let [c-pod (pod/make-pod (get-env))]
(boot.util/info "New pod taken: %s\n" c-pod)
(pod/with-eval-in c-pod
(boot.util/info "Hi from pod no. %s.\n" ~i))
(pod/destroy-pod c-pod)))
.start
.join)
(recur (inc i)))) The reason I haven't seen this with ShimDandy before is likely because I think I can fix this internally in ShimDandy, by adding a |
@tobias that sounds great, thanks for the detailed explanation! In the |
@micha I'll see if I can get out a ShimDandy release today. It's probably a good idea to call |
#314 should fix it. I went with the simpler solution of ensuring |
Closed via #314 |
Thanks for the attention on this, and sorry I didn't follow up before the release. I tested this again with boot 2.4.2. The class leak has been (significantly) mitigated but not resolved. New classes are still being created at the rate of ~2,000 per watch invocation compared to ~10,000 before. The above minimal cases probably help isolate aspects of the leak, but they don't fully model the case that I reported which is of the variety of Please see this repo again: https://github.com/stephenbrady/boot-pod-leak. The difference in reproducing tests suggests that |
@stephenbrady unless you supply some JVM option like Probably good to document this on the JVM Options page. |
Sorry, but that's not what I observe in the repo I published. All setting that JVM option does is trigger an OOM exception in Java8 after so many classes have been created and not released. I still see significant class leakage. GC is not releasing those classes when under pressure. Since the JVM chooses to OOM instead of pausing the JVM to GC those classes, it means there's a class leak. |
I can replicate the behaviour I described (i.e. classes are GCd) with your project (ref Also just to double check - is the output of EDIT No need to try the stuff below unless you want to test without having to run Can you try putting this into a file #!/usr/bin/env boot
(require '[boot.pod :as pod])
(defn -main [& args]
(println "Hello")
(loop [i 0]
(let [c-pod (pod/make-pod (get-env))]
(boot.util/info "New pod taken: %s\n" c-pod)
(pod/with-eval-in c-pod
(boot.util/info "Hi from pod no. %s.\n" ~i))
(pod/destroy-pod c-pod)
(recur (inc i))))) |
Hmm, an old version of boot was sneaking in as I was switching between repos. Sigh...sorry for the churn. |
No worries! 👍 |
@stephenbrady - I ran your test app, with a This was with: $ boot --version
#https://github.com/boot-clj/boot
#Mon Nov 23 17:51:23 EST 2015
BOOT_JVM_OPTIONS=-client -XX\:+TieredCompilation -XX\:TieredStopAtLevel\=1 -Xmx2g -XX\:+UseConcMarkSweepGC -XX\:+CMSClassUnloadingEnabled -Xverify\:none
BOOT_CLOJURE_NAME=org.clojure/clojure
BOOT_VERSION=2.4.2
BOOT_CLOJURE_VERSION=1.7.0
#App version: 2.4.2
$ java -version
openjdk version "1.8.0_65"
OpenJDK Runtime Environment (build 1.8.0_65-b17)
OpenJDK 64-Bit Server VM (build 25.65-b01, mixed mode) I'll let it run for a few hours and see if the behavior changes. Is there any thing else I could try to help recreate it? |
Oops, I see y'all have figured it out. Ignore my last comment then :) |
Yep, I finally got the sawtooth graph too after I pinned down the boot configuration on my machine. Thanks again. |
Hello folks, the problem is still there when it comes to using tasks that use pods (like Does it sound like a good idea? The problem for me happens when I run |
This repo produces a class leak with each invocation of
test
byboot watch
.https://github.com/stephenbrady/boot-pod-leak
In writing custom boot tasks, I see the same kind of class leak when using either
boot.pod/make-pod
withboot.pod/destroy-pod
orboot.pod/pod-pool
with:refresh
.The text was updated successfully, but these errors were encountered: