I'm trying to prove two simple facts about how Ruby works:
* Ruby can GC a Thread that has run to completion if you no longer have any references to it, even if the value() have never been collected
* Ruby cannot GC a running Thread, even if there are no references to it
Some new code I have relies on these truths. Simple scripts I've written seems to indicate they are accurate, but I would love to hear from someone who knows these to be true, or untrue.
Thanks in advance for any information you can provide.
James Edward Gray II
Actually, this is difficult to judge. For example, this script has odd results on my machine. The Thread count does drop, but not all the way:
#!/usr/bin/env ruby -wKU
def show_thread_count
count = 0
ObjectSpace.each_object(Thread) { |obj| count += 1 }
p count
end
show_thread_count
5.times do
Thread.new do
date = `sleep 1 && date`
end
end
20.times do
sleep 0.2
3.times { GC.start }
show_thread_count
end
__END__
Here's a pretty typical output, though it varies a little:
$ ruby testing_thread_gc.rb
1
6
3
Thoughts?
James Edward Gray II
···
On Feb 10, 2009, at 4:51 PM, James Gray wrote:
I'm trying to prove two simple facts about how Ruby works:
* Ruby can GC a Thread that has run to completion if you no longer have any references to it, even if the value() have never been collected
* Ruby cannot GC a running Thread, even if there are no references to it
Simple scripts I've written seems to indicate they are accurate…
James Gray wrote:
* Ruby can GC a Thread that has run to completion if you no longer have any references to it, even if the value() have never been collected
Not sure.
* Ruby cannot GC a running Thread, even if there are no references to it
Unfortunately, this part is true, as Ruby has not solved the Halting Problem.
It might be possible to collect a thread if you have very specific knowledge about when it is no longer needed. The hack I've been playing with lately is to have all access to the thread be through a specific object or set of objects, and reap the thread in the finalizer(s) of those object(s).
The part I haven't solved is circular references -- anything one thread has a reference to can't be collected as long as that thread is running, so if thread A knows about thread B, which also knows about thread A, they will have to be manually cleaned, even if that knowledge is purely through such proxy objects.
Oh -- the above rambling might make sense in context. I'm writing an actor library. I can picture a state where a collection of actors should be collected, as they're all out of messages and only referred to by each other -- but while I theoretically should be able to write a garbage collector for that, I can't figure out how to do it in Ruby without at least writing a C extension.
James Gray wrote:
def show_thread_count
count = 0
ObjectSpace.each_object(Thread) { |obj| count += 1 }
p count
end
Btw, this is the same as
def show_thread_count
p ObjectSpace.each_object(Thread) {}
end
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
James Gray wrote:
* Ruby can GC a Thread that has run to completion if you no longer have any references to it, even if the value() have never been collected
Not sure.
It seems this is at least somewhat true. See the script I posted earlier in this thread for an example. I would love to know why it can't totally clear them in that example though.
* Ruby cannot GC a running Thread, even if there are no references to it
Unfortunately, this part is true, as Ruby has not solved the Halting Problem.
Well, it happens to help me in this case, so I'll call it a bonus. 
James Edward Gray II
···
On Feb 10, 2009, at 6:25 PM, David Masover wrote: