First, sorry we don't have comments yet. I'm the author, so you no longer have to be enraged. Perhaps just annoyed.
Second, with Ruby 2.1, out of the box, this code:
while true do
"a" * (1024 ** 2)
end
leads to infinite process growth. There should be no need for "memory doubling" to run this code -- you're generating throwaway strings of identical size. Similar code, in other languages, does not lead to out of control memory consumption.
Also, the problem isn't caused by disabling the GC. This happens in stock Ruby 2.1. Disabling the GC (and running it once per request) is the fix for the problem.
> There should be no need for "memory doubling" to run this code -- you're generating throwaway strings of identical size.
How do you know they are throwaway?
Your code involves two method calls. While it would be unlikely that someone has overridden them given that they are core String and Fixnum methods, it is perfectly possible. E.g:
class String;
alias :old :*
def * right
$store ||= []
$store << self
old(right)
end
end
"foo" * 5
"bar" * 3
p $store
In other words, even with seemingly innocent calls like that, it takes extra work to be able to reuse that memory without a full GC pass. It's certainly not impossible, but it's not there yet.
So I agree with you in principle, but this is one of those areas where the malleability of Ruby objects makes it tricky to optimize.
(one possible example approach is to set aside a bit to indicate "has at least once been stored somewhere where it can escape" as "poor mans escape analysis" - if your object is only ever stored in local variables that have no been captured by a lambda, or passed as arguments, then it can't escape higher than where it was created, and so you can take shortcuts, otherwise you'd still need a full gc pass)
First, sorry we don't have comments yet. I'm the author, so you no longer have to be enraged. Perhaps just annoyed.
Second, with Ruby 2.1, out of the box, this code:
leads to infinite process growth. There should be no need for "memory doubling" to run this code -- you're generating throwaway strings of identical size. Similar code, in other languages, does not lead to out of control memory consumption.Also, the problem isn't caused by disabling the GC. This happens in stock Ruby 2.1. Disabling the GC (and running it once per request) is the fix for the problem.