Here is my script
require 'benchmark'
require 'ostruct'
Benchmark.bmbm do |x|
n=10000
array = n.times.map{ |i| OpenStruct.new id: i }
hash = Hash[*(array.map{ |s| [s.id, s] }.flatten)]
x.report('array') do
array.find{ |s| s.id == 100}
end
x.report('hash') do
hash[100]
end
end
why with n=100000 I get:
stack level too deep (SystemStackError)
?
not related, but, am I building the hash in the best way?
You’re passing tens of thousands of arguments to a method and that’s just too many for Ruby to handle, causing a stack error.
Instead just pass the un-flattened, un-splatted mapped array to Hash.[], since it accepts that just fine and gives the same (correct) result (without a SystemStackError):
Hash[array.map { |s| [s.id, s] }]
As an aside, we can see the argument count is in fact the issue (rather than specifically Hash.[]) with a simple test:
def f(*args); end
f(*(1..1000000).to_a) #<SystemStackError: stack level too deep>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With