is defined? fast?

G

George Moschovitis

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.
 
R

Robert Klemme

George Moschovitis said:
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:
http://www.rubygarden.org/ruby

Regards

robert
 
G

George Moschovitis

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

gabriele renzi

Robert Klemme ha scritto:
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
 
J

Josef 'Jupp' Schugt

George said:
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
 
M

Mark Hubbart

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.

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
 
E

Eric Hodel

--Apple-Mail-11--1061695470
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset=US-ASCII; format=flowed

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.

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)

--
Eric Hodel - (e-mail address removed) - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

--Apple-Mail-11--1061695470
content-type: application/pgp-signature; x-mac-type=70674453;
name=PGP.sig
content-description: This is a digitally signed message part
content-disposition: inline; filename=PGP.sig
content-transfer-encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (Darwin)

iD8DBQFB7am7MypVHHlsnwQRAlHMAJ47Aqo0w2c6RtXr3+MgJi3Xz1DeBACgyWpT
lBwFzKljsEjWCtdbIXYOYAI=
=85s1
-----END PGP SIGNATURE-----

--Apple-Mail-11--1061695470--
 
R

Robert Klemme

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. :)

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... :)

Kind regards

robert
 
F

Florian Gross

Robert said:
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. :)

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.
 
J

Joel VanderWerf

Florian said:
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
 
E

Eric Hodel

--Apple-Mail-16--995960007
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset=US-ASCII; format=flowed

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. :)

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... :)

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

statement if defined? something

vs.

statement if $global

I like being specific.

--
Eric Hodel - (e-mail address removed) - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

--Apple-Mail-16--995960007
content-type: application/pgp-signature; x-mac-type=70674453;
name=PGP.sig
content-description: This is a digitally signed message part
content-disposition: inline; filename=PGP.sig
content-transfer-encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (Darwin)

iD8DBQFB7qqDMypVHHlsnwQRAqHsAJ9Xy4dnzr95vk71Yl+IHgsxLTjdMgCfTn5h
N3CZl9ogw+NkmFLLn73FIU0=
=ZtyN
-----END PGP SIGNATURE-----

--Apple-Mail-16--995960007--
 
A

Austin Ziegler

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. :)

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
 
B

Bill Kelly

Hi,

From: "Austin Ziegler said:
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
 
A

Austin Ziegler

Is the top part semantically different from just,

module Text; end

?


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 ;)

-austin
 
S

Sea&Gull

Eric said:
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"

?

:)

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

Robert Klemme

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

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
 
G

George Moschovitis

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

-g.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,166
Messages
2,570,901
Members
47,442
Latest member
KevinLocki

Latest Threads

Top