Is defined? fast?

Hello everyone, I have a simple question:

is 'if defined?(MyFlag)' as fast as 'if $my_flag'
or is it much slower?

Any information will be appreciated.

George.

"George Moschovitis" <george.moschovitis@gmail.com> schrieb im Newsbeitrag
news:1105968115.995603.227690@f14g2000cwb.googlegroups.com...

Hello everyone, I have a simple question:

is 'if defined?(MyFlag)' as fast as 'if $my_flag'
or is it much slower?

Any information will be appreciated.

You cannot compare them as both have different functionality: defined?
checks whether a var is defined while the other test uses the var value.

I think there is a wiki page about this but I cannot find it at the
moment. The wiki is here:

Regards

    robert

A quick check suggests that defined? *might* be just slightly slower.
But probably not enough to matter. You may want to profile your
scripts (just "require 'profile'" at the top) and see what's best in
your case.

These results might be affected by caching of data; if you use
different variables for each of the 5000 checks, it could easily come
out different.

mark@eMac% ruby -rprofile
def a
  5000.times{true if defined? Foo}
end
def b
  5000.times{true if $foo}
end

a
b

  % cumulative self self total
time seconds seconds calls ms/call ms/call name
95.92 0.47 0.47 2 235.00 235.00 Integer#times
  2.04 0.48 0.01 1 10.00 10.00 Profiler__.start_profile
  0.00 0.48 0.00 1 0.00 230.00 Object#b
  0.00 0.48 0.00 1 0.00 490.00 #toplevel
  0.00 0.48 0.00 2 0.00 0.00 Module#method_added
  0.00 0.48 0.00 1 0.00 240.00 Object#a

cheers,
Mark

···

On Mon, 17 Jan 2005 22:26:17 +0900, George Moschovitis <george.moschovitis@gmail.com> wrote:

Hello everyone, I have a simple question:

is 'if defined?(MyFlag)' as fast as 'if $my_flag'
or is it much slower?

of course they are different. But is defined? *much* slower than the
simple check? I 'll hava a look at the wiki

Robert Klemme ha scritto:

"George Moschovitis" <george.moschovitis@gmail.com> schrieb im Newsbeitrag
news:1105968115.995603.227690@f14g2000cwb.googlegroups.com...

Hello everyone, I have a simple question:

is 'if defined?(MyFlag)' as fast as 'if $my_flag'
or is it much slower?

Any information will be appreciated.

You cannot compare them as both have different functionality: defined?
checks whether a var is defined while the other test uses the var value.

I think he's wondering if writing stuff like

conditionalstuff
if defined? foo

vs
foo=bar
conditionalstuff
if foo

No, profile cannot detect a global test or defined? being called, because they are not method calls. You want to use benchmark.rb.

defined? MyFlag is at best almost half as fast as $my_flag, probably because defined? does not just return true (it returns a String).

$ cat x.rb
require 'benchmark'

TIMES = ARGV.shift || 100_000
$x = true
@x = true
@@x = true

module X; X = true; end

Benchmark.benchmark do |bm|
   bm.report "baseline " do
   end

   bm.report "defined? Nested::Constant" do
     TIMES.times do
       true if defined? X::X
       true if defined? X::Y
     end
   end

   bm.report "defined? Constant " do
     TIMES.times do
       true if defined? Benchmark
       true if defined? NoSuchConst
     end
   end

   bm.report "defined? $global " do
     TIMES.times do
       true if defined? $x
       true if defined? $y
     end
   end

   bm.report "defined? local " do
     TIMES.times do
       true if defined? bm
       true if defined? no_such_local
     end
   end

   bm.report "defined? @var " do
     TIMES.times do
       true if defined? @x
       true if defined? @no_such_ivar
     end
   end

   bm.report "defined? @@var " do
     TIMES.times do
       true if defined? @@x
       true if defined? @@no_such_cvar
     end
   end

   bm.report "$global " do
     TIMES.times do
       true if $x
       true if $y
     end
   end
end

$ ruby x.rb
baseline 0.000000 0.000000 0.000000 ( 0.000046)
defined? Nested::Constant 0.680000 0.000000 0.680000 ( 0.884762)
defined? Constant 0.370000 0.000000 0.370000 ( 0.458034)
defined? $global 0.320000 0.000000 0.320000 ( 0.336950)
defined? local 0.330000 0.000000 0.330000 ( 0.345521)
defined? @var 0.370000 0.000000 0.370000 ( 0.455369)
defined? @@var 0.370000 0.000000 0.370000 ( 0.400793)
$global 0.150000 0.000000 0.150000 ( 0.174302)

PGP.sig (186 Bytes)

···

On 18 Jan 2005, at 15:24, Mark Hubbart wrote:

On Mon, 17 Jan 2005 22:26:17 +0900, George Moschovitis > <george.moschovitis@gmail.com> wrote:

Hello everyone, I have a simple question:

is 'if defined?(MyFlag)' as fast as 'if $my_flag'
or is it much slower?

A quick check suggests that defined? *might* be just slightly slower.
But probably not enough to matter. You may want to profile your
scripts (just "require 'profile'" at the top) and see what's best in
your case.

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

George Moschovitis wrote:

But is defined? *much* slower than the simple check?

Perhaps the following analogy helps understanding the problem with your
question:

When asking if a humvee is much slower than an Alfa Romeo it is a very
good idea to provide a description of the terrain one refers to: On a
motodrome an Alfa Romeo of course is much faster than a humvee. During a
traffic jam both cars are equally fast. When leaving roads the humvee
has good chances of being much faster than an Alfa Romeo (that may not
even move one meter). HTH.

Fiat tux,

Josef 'Jupp' Schugt

···

--
The most severe crime in Germany is being on board of a plane that is
hijacked. Separation of powers is bypassed, the only punishment for it
is death, no legal proceedigs are necessary. It is the *only* crime for
which germans may sentence you to death. Ask German DoD for details.

"Eric Hodel" <drbrain@segment7.net> schrieb im Newsbeitrag
news:12DE17DB-69B1-11D9-AFB0-000D93436DA0@segment7.net...

Looks like the simple var check is better performance wise. Personally I
never felt the need for defined? - only during my initial Ruby stages,
when I carried some Perl thinking with me; but never after I got rid of
that. :slight_smile:

Ah, and btw, you don't need the "true if ". Not that it matters
performance wise since you applied it everywhere - but I prefer to reduce
redundancy... :slight_smile:

Kind regards

    robert

Thank, you for this detailed answer.
I really appreciate the time you 've put into this!

-g.

Robert Klemme wrote:

Personally I never felt the need for defined? - only during my
initial Ruby stages, when I carried some Perl thinking with me; but
never after I got rid of that. :slight_smile:

I always thought it was there mostly for using it in IRB, not in actual
code. (E.g. to ask Ruby how it understands a construct.)

But it does at least make sense in real code in the defined?(Constant) case.

"Eric Hodel" <drbrain@segment7.net> schrieb im Newsbeitrag
news:12DE17DB-69B1-11D9-AFB0-000D93436DA0@segment7.net...

Looks like the simple var check is better performance wise. Personally I
never felt the need for defined? - only during my initial Ruby stages,
when I carried some Perl thinking with me; but never after I got rid of
that. :slight_smile:

module M
   def functionality
     do_stuff if @x
   end
end

class C
   include M
end

C.new.functionality

With ruby -w, this will give an 'uninitialized instance variable' warning. M#functionality needs to be written this way to get rid of the warning:

module M
   def functionality
     @x = default unless defined? @x
     do_stuff if @x
   end
end

Ah, and btw, you don't need the "true if ". Not that it matters
performance wise since you applied it everywhere - but I prefer to reduce
redundancy... :slight_smile:

I feel it is necessary. You're benchmarking the case of:

statement if defined? something

vs.

statement if $global

I like being specific.

PGP.sig (186 Bytes)

···

On 19 Jan 2005, at 09:46, Robert Klemme wrote:

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

I now use it like this:

  unless defined?(Text)
    module Text; end
  end

  class Text::Format
    ...
  end

Saves me some indentation levels and keeps the code readable and working.

-austin

···

On Thu, 20 Jan 2005 02:46:01 +0900, Robert Klemme <bob.news@gmx.net> wrote:

Looks like the simple var check is better performance wise. Personally I
never felt the need for defined? - only during my initial Ruby stages,
when I carried some Perl thinking with me; but never after I got rid of
that. :slight_smile:

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Florian Gross wrote:

Robert Klemme wrote:

Personally I never felt the need for defined? - only during my
initial Ruby stages, when I carried some Perl thinking with me; but
never after I got rid of that. :slight_smile:

I always thought it was there mostly for using it in IRB, not in actual
code. (E.g. to ask Ruby how it understands a construct.)

But it does at least make sense in real code in the defined?(Constant) case.

The following idiom is useful in mixins:

   module Mixin
     def meth
       super if defined?(super)
       # add some behavior here
     end
   end

Hi,

  unless defined?(Text)
    module Text; end
  end

  class Text::Format
    ...
  end

Saves me some indentation levels and keeps the code readable and working.

Is the top part semantically different from just,

module Text; end

?

Regards,

Bill

···

From: "Austin Ziegler" <halostatue@gmail.com>

Eric Hodel wrote:

"Eric Hodel" <drbrain@segment7.net> schrieb im Newsbeitrag
news:12DE17DB-69B1-11D9-AFB0-000D93436DA0@segment7.net...

Looks like the simple var check is better performance wise. Personally I
never felt the need for defined? - only during my initial Ruby stages,
when I carried some Perl thinking with me; but never after I got rid of
that. :slight_smile:

module M
  def functionality
    do_stuff if @x
  end
end

class C
  include M
end

C.new.functionality

With ruby -w, this will give an 'uninitialized instance variable' warning. M#functionality needs to be written this way to get rid of the warning:

module M
  def functionality
    @x = default unless defined? @x
    do_stuff if @x
  end
end

What about

@x ||= "default"

?

:slight_smile:

Although
@x = default unless defined? @x
looks much more readable :slight_smile:

···

On 19 Jan 2005, at 09:46, Robert Klemme wrote:

"Eric Hodel" <drbrain@segment7.net> schrieb im Newsbeitrag
news:2068C17C-6A4A-11D9-AFB0-000D93436DA0@segment7.net...

>
> "Eric Hodel" <drbrain@segment7.net> schrieb im Newsbeitrag
> news:12DE17DB-69B1-11D9-AFB0-000D93436DA0@segment7.net...
>
> Looks like the simple var check is better performance wise.
> Personally I
> never felt the need for defined? - only during my initial Ruby stages,
> when I carried some Perl thinking with me; but never after I got rid

of

> that. :slight_smile:

module M
   def functionality
     do_stuff if @x
   end
end

class C
   include M
end

C.new.functionality

With ruby -w, this will give an 'uninitialized instance variable'
warning. M#functionality needs to be written this way to get rid of
the warning:

module M
   def functionality
     @x = default unless defined? @x

You can as well do "@x ||= nil" to get rid of the warning.

11:25:49 [otrs-1006999]: ruby -w -e 'class Foo; def x() @bar end
end;Foo.new.x'
-e:1: warning: instance variable @bar not initialized
13:00:17 [otrs-1006999]: ruby -w -e 'class Foo; def x() @bar ||= nil end
end;Foo.new.x'
13:00:34 [otrs-1006999]:

     do_stuff if @x
   end
end

> Ah, and btw, you don't need the "true if ". Not that it matters
> performance wise since you applied it everywhere - but I prefer to
> reduce
> redundancy... :slight_smile:

I feel it is necessary. You're benchmarking the case of:

statement if defined? something

vs.

statement if $global

I like being specific.

Hm, but as "statement" is the same in both cases you could equally well
just benchmark the boolean expression. If you expect effects due to the
statement being there then that should probably a realistic statement.

Just my 0.02EUR...

Kind regards

    robert

···

On 19 Jan 2005, at 09:46, Robert Klemme wrote:

irb(main):001:0> class Text; end
  => nil
  irb(main):002:0> module Text; end
  TypeError: Text is not a module
          from (irb):2
  irb(main):003:0>

It's simply defensive programming.

I could shorten it with:

  module Text; end unless defined?(Text)

I haven't done this with all of my libraries, but mostly on those
libraries where I am using the module as a namespace (e.g.,
Text::Format, Text::Hyphen, and now Kaspar's Text::Reform).

It's not perfect, but it's better than it could be :wink:

-austin

···

On Thu, 20 Jan 2005 05:52:59 +0900, Bill Kelly <billk@cts.com> wrote:

From: "Austin Ziegler" <halostatue@gmail.com >

unless defined?(Text)
  module Text; end
end

class Text::Format
  ...
end

Saves me some indentation levels and keeps the code readable and working.

Is the top part semantically different from just,

module Text; end

?

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca