-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Using Hystrix Observable for a zip operation leading to a memory leak #1370
Comments
Thanks for the report, @bijukunjummen . Can you provide more details on the 3 |
Hi @mattrjacobs , thanks for your response. Yes, they are stock Hystrix commands created using a tiny wrapper - https://github.com/bijukunjummen/obs-leak-test/blob/master/src/main/java/leaktest/commands/Part1Command.java I have put a sample project here - https://github.com/bijukunjummen/obs-leak-test which replicates this behavior. In the sample I have forcibly opened the circuit for the first command through this property - The result in the app is as expected, but because of the above leak ultimately the app crashes. |
One more observation - this happens only if there is no fallback available in the command with open circuit. With a clean fallback there is no build up in memory. |
I just added and ran a jmh test for single command execution when the circuit is forced open. This didn't uncover a memory leak I then removed the fallback and re-ran the test. This also did not exhibit a memory leak My next guess would be to add an Observable.zip and see if there's anything interesting going on external to the command. |
I repeated a jmh test and eliminated all other dependencies that I had in my previous sample @mattrjacobs and am able to replicate the leak. Here is the sample that I have - https://github.com/bijukunjummen/obs-leak-benchmark/blob/master/src/main/java/obs/ObservableZipBenchmark.java With the benchmarks I quickly got a "GC overhead limit exceeded error":
|
Thanks for the benchmark, @bijukunjummen, that's very helpful. The first thing I tried was using Observable.error({some exception}) for |
My first interesting finding (which I'd love for you to verify) is that switching the order of the 2 Observables does not result in the leak. That leads me to believe that somehow the Zip operator is seeing the error and exiting early, and some data structure is being references somewhere. Still chasing that down... |
Yes, able to replicate the behavior you are seeing @mattrjacobs! A workaround that I have used is to explicitly trap the exception, say using fugue library, then the leak is not there also :
|
OK, finally got to the bottom of this. The behavior of In the case of Hystrix, this manifested as an unsubscribe before a subscribe. This isn't something that we had tests for, since the only way to induce it is through an operator like Once I made that realization, the fix is straightforward. Hystrix will now return I used the supplied jmh test to verify that doing this prevents any references from building up. Thanks again for supplying that! |
Awesome, great to hear that you have found the root cause and that the fix is simple. Thanks for digging into it. I will try out the PR and let you know how it goes. |
I was able to test the PR @mattrjacobs, it works perfectly, thanks for the quick turnaround. |
Great, thanks for the confirmation |
Hi, I am not sure if this issue fits here or with rx-java. The behavior I am seeing is if I return an
Observable
from a set of Hystrix Commands usingtoObservable
method and use that later in a zip call, say:with some of the circuits open, I see a leak with a lot of instances of
OperatorZip
building up in memory, here is how the instances look using Memory Analyzer tool:This behavior is not seen if I were to wrap the hystrix call using
Observable.create
and then use it in a zip operation, which leads me to think that the issue is somewhere in Hystrix libraries and not in rx-java itself.Rxjava version - 1.1.5
Hystrix version - 1.5.3
The text was updated successfully, but these errors were encountered: