Do Ruby objects have a size limit?
Asked Answered
A

1

9

I'm building some large strings which have a short lifetime within the application. Will the String objects grow arbitrarily large up to the physical limits of the ruby instance?

What I'm wondering is if, without any intervention in limiting the string size, my application would get hosed by running out of memory, or whether it would degrade gracefully.

Thanks for any input!

Acanthous answered 3/9, 2010 at 18:37 Comment(0)
S
13

There is a limit. A String can be 2**31 - 1 (and accordingly 2**63 - 1 on 64 bit ruby). You can see the limit with:

>> s = String.new("1" * (2**32))
RangeError: bignum too big to convert into `long'
    from (irb):3:in `*'
    from (irb):3
>> s = String.new("1" * (2**31))
RangeError: bignum too big to convert into `long'
    from (irb):4:in `*'
    from (irb):4

Having said that, while you could try to allocate a string that big it will likely fail (at least on a 32 bit system as typically the maximum amount of memory a process can allocate is between 2.5 and 3GB and a 2**31 - 1 length string is nearly 2GB by itself.) As seen:

>> "1" * (2**30)
NoMemoryError: failed to allocate memory
    from /usr/lib/ruby/1.8/irb.rb:310:in `inspect'
    from /usr/lib/ruby/1.8/irb.rb:310:in `output_value'
    from /usr/lib/ruby/1.8/irb.rb:159:in `eval_input'
    from /usr/lib/ruby/1.8/irb.rb:271:in `signal_status'
    from /usr/lib/ruby/1.8/irb.rb:155:in `eval_input'
    from /usr/lib/ruby/1.8/irb/ruby-lex.rb:244:in `each_top_level_statement'
    from /usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in `loop'
    from /usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in `each_top_level_statement'
    from /usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in `catch'
    from /usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in `each_top_level_statement'
    from /usr/lib/ruby/1.8/irb.rb:154:in `eval_input'
    from /usr/lib/ruby/1.8/irb.rb:71:in `start'
    from /usr/lib/ruby/1.8/irb.rb:70:in `catch'
    from /usr/lib/ruby/1.8/irb.rb:70:in `start'
    from /usr/bin/irb:13
Maybe IRB bug!!

I don't believe there is any way to catch the NoMemoryError.

Updated to reflect the comment from sepp2k

Seavey answered 3/9, 2010 at 19:16 Comment(3)
Actually it can be as big as 2**31 - 1 (and accordingly 2**63 - 1 on 64 bit ruby).Tiernan
Is that 2**31 - 1 characters or 2**31 -1 bytes? Also, isn't catching a NoMemoryError a matter of saying rescue Exception rather than rescue (the latter only rescuing relatively mild exceptions)? (To say nothing of neversaydie...)Patric
2**31 - 1 bytes. Including rescue Exception does catch the NoMemoryError but it doesn't seem to actually perform the allocation (since it returns immediately.)Seavey

© 2022 - 2024 — McMap. All rights reserved.