Forum: Ruby nil? takes much time

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
2c7c807a1df0c76a8fc823c709b501a9?d=identicon&s=25 Victor Shepelev (Guest)
on 2006-04-28 00:52
(Received via mailing list)
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 :)

Victor.
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-04-28 04:09
(Received via mailing list)
On Apr 27, 2006, at 6:49 PM, Victor Shepelev wrote:

> And I've suddenly noticed (due to profile) that nil? Takes a
>
> 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
2c7c807a1df0c76a8fc823c709b501a9?d=identicon&s=25 Victor Shepelev (Guest)
on 2006-04-28 04:24
(Received via mailing list)
> > amount of time here.
> >
>
> 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

[skip]

From one side, you are right (and I've must understand all above in
myself).
What is really unpleasant - is to see how can "infrastructure" code slow
down the program. The effect "nil? is slower then direct if" is
waitable.
What is UNwaitable - that nil? is *noticable* slower (in profile report
it
was fifth line from top). I hope thing would go better in next ruby's
version.

Offtopic: BTW, can somebody comment on following questions:
1. How much 1.9 faster than 1.8.4, and how much it stable?
2. When can we wait for Rite?

Thanks.

Victor.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2006-04-28 10:15
(Received via mailing list)
2006/4/28, Victor Shepelev <vshepelev@imho.com.ua>:
> Offtopic: BTW, can somebody comment on following questions:
> 1. How much 1.9 faster than 1.8.4, and how much it stable?

There might not be an easier answer to that: could be that some
applications are faster and some slower.

> 2. When can we wait for Rite?

Any time. ;-)

Kind regards

robert
This topic is locked and can not be replied to.