Created
August 7, 2012 04:16
-
-
Save ryanlecompte/3281509 to your computer and use it in GitHub Desktop.
ActiveRecord memory leak with multiple threads?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# It appears that when I perform a query with AR via multiple threads, | |
# the instantiated objects do not get released when a GC is performed. | |
threads = Array.new(5) { Thread.new { Foo.where(:status => 2).all.first(100).each { |f| f.owner.first_name } } } | |
threads.each(&:join) | |
threads = nil | |
GC.start | |
ObjectSpace.each_object(Foo).count # => instances still exist | |
# ---------------- | |
Foo.where(:status => 2).all.first(100).each { |f| f.owner.first_name } | |
GC.start | |
ObjectSpace.each_object(Foo).count # => 0 | |
Thank you @mboeh. That's very interesting and very good to know!
Things in ObjectSpace are not necessarily live instances. There are shortcut tricks you can use to force memory to be free'd / overwritten (in MRI only, where it's full of hacks at the C level "for speed"). Assuming that any Ruby GC will be fully deterministic around GC.start behavior is unlikely to be productive.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I did my own testing and determined that setting threads to nil is insufficient to get the threads GC'd. You need to do threads.clear.
This is true even if you wrap the code creating the threads in a method, which is surprising -- I'd expect the local variable reference to be lost outside that method's scope, and the threads to be available for GC.
It seems that threads stored in an array in a local variable might not be available to GC when expected. I have a demonstration at https://gist.github.com/3287930 .