Do Ruby Objects Have a Size Limit

Do Ruby objects have a size limit?

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

Ruby/Rails - Limit the size of a object/hash

First of all, if you'd like to have pagination, I strongly suggest taking a look at will_paginate

Alternatively, you can do the following to read the first 10 records only.

<% @events.first(10).each do |event| %>
<p><%= event.name %></p>
<% end %>

Or the last 10 records

<% @events.last(10).each do |event| %>
<p><%= event.name %></p>
<% end %>

I didn't test it but you get the point.

Is there a limit on the size of an array in ruby?

There is not a software limit imposed by Ruby, but there is a limit as to how much the process can support. If you have a regular home server running the Ruby server, it would be able to handle an array until the array became too large, at which point it would begin to 'bog down', lag, crash, etc. On the other hand, if you had an extremely powerful corporate server, it could handle a much larger array, but would still eventually crash/lag if the array became too large for the process and the hardware (memory) to handle.

I don't have any concrete numbers for you, because it all depends on the hardware and software on the server.

Is there a size limit on data stored in the flash[] object?

They are stored in the session, just like using session[:big_data].

Session has a limit of 4K, however, you can change your session store in config/initializers/session_store.rb

Here is an example of an alternate session store https://github.com/roidrage/redis-session-store

Rails 3.1 limit user created objects

Try something like this:

class User < ActiveRecord::Base
has_many :things
end

class Things <ActiveRecord::Base
belongs_to :user
validate :thing_count_within_limit, :on => :create

def thing_count_within_limit
if self.user.things(:reload).count >= 5
errors.add(:base, "Exceeded thing limit")
end
end
end

Edit: updated for Rails 3

Working with a large data object between ruby processes

A sinatra app will work, but the {un}serializing, and the HTML parsing could impact performance compared to a DRb service.

Here's an example, based on your example in the related question. I'm using a hash instead of an array so you can use user ids as indexes. This way there is no need to keep both a table on interests and a table of user ids on the server. Note that the interest table is "transposed" compared to your example, which is the way you want it anyways, so it can be updated in one call.

# server.rb
require 'drb'

class InterestServer < Hash
include DRbUndumped # don't send the data over!

def closest(cur_user_id)
cur_interests = fetch(cur_user_id)
selected_interests = cur_interests.each_index.select{|i| cur_interests[i]}

scores = map do |user_id, interests|
nb_match = selected_interests.count{|i| interests[i] }
[nb_match, user_id]
end
scores.sort!
end
end

DRb.start_service nil, InterestServer.new
puts DRb.uri

DRb.thread.join

# client.rb

uri = ARGV.shift
require 'drb'
DRb.start_service
interest_server = DRbObject.new nil, uri

USERS_COUNT = 10_000
INTERESTS_COUNT = 500

# Mock users
users = Array.new(USERS_COUNT) { {:id => rand(100000)+100000} }

# Initial send over user interests
users.each do |user|
interest_server[user[:id]] = Array.new(INTERESTS_COUNT) { rand(10) == 0 }
end

# query at will
puts interest_server.closest(users.first[:id]).inspect

# update, say there's a new user:
new_user = {:id => 42}
users << new_user
# This guy is interested in everything!
interest_server[new_user[:id]] = Array.new(INTERESTS_COUNT) { true }

puts interest_server.closest(users.first[:id])[-2,2].inspect
# Will output our first user and this new user which both match perfectly

To run in terminal, start the server and give the output as the argument to the client:

$ ruby server.rb
druby://mal.lan:51630

$ ruby client.rb druby://mal.lan:51630
[[0, 100035], ...]

[[45, 42], [45, 178902]]

In Ruby, can I limit the amount of drilling down a object does when displaying itself in irb or when using .inspect?

Redefine inspect in Puzzle and display only what you want.

For example:

def inspect
"Puzzle with size #{rows.size}"
end

How to limit the number of items that can be added to an ActiveRecord array

You can use a before_add callback (scroll down to heading "Association callbacks") on your association to enforce the behavior

Should any of the before_add callbacks throw an exception, the object does not get added to the collection. Same with the before_remove callbacks; if an exception is thrown the object doesn’t get removed.

Arrays in Ruby: Take vs Limit vs First

  1. limit is not an array method
  2. take requires an argument; it returns an empty array if the array is empty.
  3. first can be called without an argument; it returns nil if the array is empty and the argument is absent.

Source for 2.0 take

              static VALUE
rb_ary_take(VALUE obj, VALUE n)
{
long len = NUM2LONG(n);
if (len < 0) {
rb_raise(rb_eArgError, "attempt to take negative size");
}
return rb_ary_subseq(obj, 0, len);
}

Source for 2.0 first:

              static VALUE
rb_ary_first(int argc, VALUE *argv, VALUE ary)
{
if (argc == 0) {
if (RARRAY_LEN(ary) == 0) return Qnil;
return RARRAY_PTR(ary)[0];
}
else {
return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
}
}

In terms of Rails:

  1. limit(5) will add the scope of limit(5) to an ActiveRecord::Relation. It can not be called on an array, so limit(5).limit(4) will fail.

  2. first(5) will add the scope of limit(5) to an ActiveRecord::Relation. It can also be called on an array so .first(4).first(3) will be the same as .limit(4).first(3).

  3. take(5) will run the query in the current scope, build all the objects and return the first 5. It only works on arrays, so Model.take(5) will not work, though the other two will work.



Related Topics



Leave a reply



Submit