From: "Mauricio Fernández" Date: 2004-07-03T08:02:57+09:00 Subject: Re: slow method searching? On Sat, Jul 03, 2004 at 06:56:31AM +0900, David Garamond wrote: > $ time ruby -e'a=(1..1000000).to_a; a.classx' > -e:1: undefined method `classx' for # (NoMethodError) > > real 0m36.652s > user 0m16.040s > sys 0m0.090s > > $ time ruby -e'a=(1..1000000).to_a; b=1; b.classx' > -e:1: undefined method `classx' for 1:Fixnum (NoMethodError) > > real 0m1.593s > user 0m0.690s > sys 0m0.010s > > > Why does it take longer and longer for Ruby to throw NoMethodError for > large arrays? What is going on here? This happens with hash too. When the exception is printed, a string representation of the associated object is created by calling #inspect. See name_err_mesg_to_str in error.c: d = rb_protect(rb_inspect, obj, 0); if (NIL_P(d) || RSTRING(d)->len > 65) { inspect is always executed, and the result is only discarded if bigger than 65 chars. It would be trivial to add a test for T_ARRAY or T_HASH and avoid calling inspect if the number of elements is bigger than some N, in addition to (and before) the 65-chars check. BTW, one oddity in the implementation: ruby uses internally a constant named "message" (lower case), which you cannot access from Ruby neither as NameError::message nor with NameError.const_get("message"), however >> ObjectSpace.each_object(Class){|x| p x if x.ancestors.include? Data} NameError::message Data There's several such tricks in the implementation (like instance variables without @, etc) ;-) -- Running Debian GNU/Linux Sid (unstable) batsman dot geo at yahoo dot com People disagree with me. I just ignore them. -- Linus Torvalds, regarding the use of C++ for the Linux kernel