From: Logan Capaldo Date: 2006-04-28T11:07:39+09:00 Subject: Re: nil? takes much time On Apr 27, 2006, at 6:49 PM, Victor Shepelev wrote: > Hello all. > > In one my class I've had very simple method: > > ... > def stored? > !@db.nil? > end > ... > > And I've suddenly noticed (due to profile) that nil? Takes a > significant > amount of time here. > > Redefining the above method like > > def stored? > @db > end > > (in if's it works good) speedups the entire program. > > I'm a bit surprized :) > If you think about it, it's not all that surprising. false and nil are both immediate values, this means its very quick to check if something is not false or nil and therefore true. .nil? sends a message. Sending a message involves 1) interning the symbol :nil?. In this case that's done at compile time, so no biggee 2) Check if #nil? is in the object's singleton class? 2a) yes? Ok, create a stack frame execute the body of the method 2b) no? Check the class of the object for #nil? Is it there? yes: ok allocate stack frame and execute the body no: Traverse the inheritance tree until we find it. Sending a message is proportional to the levels of inheritance (including modules) between the objects class and the first parent class that implements the message plus the overhead of invoking a method (allocating stack frame, setting self, etc.) if @db end can be done as in pseudo-C code as if ( @db != Qnil && @db != Qfalse ) { } versus: if ( send(@db, :nil?) ) { } VALUE send(obj, message) { if ( has_singleton(obj) ) { if ( instance_respond(singleton_class_of(obj), message) ) { return invoke_method(singleton_class_of(obj), obj, message); } } if ( instance_respond(obj->class, message) { return invoke_method(obj->class, obj, message); } return send(upcast(obj, obj->class->superclass), message); } This isn't real ruby/C code, and I'm sure the real thing uses iteration instead of recursion, but you get the idea > Victor. > >