in reply to OOP - Constant Vs. Subroutine

Many reading this thread can probably already figure this out, but it hasn't been stated directly so...

Note that you can get your subs to be just as fast1 by adding "()" after each's name. That is, replace something like:

sub DoesNotChange { 5; }

with

sub DoesNotChange() { 5; }

1 But who cares? If you couldn't notice the speed difference w/o resorting to Benchmark...

- tye        

Replies are listed 'Best First'.
Re^2: OOP - Constant Vs. Subroutine ()
by shmem (Chancellor) on May 12, 2007 at 09:25 UTC
    by adding "()" after each's name
    ...which is exactly the reason why perl can optimize the sub away at compile time and makes them behave like use constant- note the two invocations
    qwurx [shmem] ~ > perl -MO=Concise,-exec -e 'use constant foo=>"5"; $c +=4+foo;' 1 <0> enter 2 <;> nextstate(main 70 -e:1) v 3 <$> const[IV 9] s 4 <#> gvsv[*c] s 5 <2> sassign vKS/2 6 <@> leave[1 ref] vKP/REFC -e syntax OK
    qwurx [shmem] ~ > perl -MO=Concise,-exec -e 'sub foo(){"5"}; $c=4+foo; +' 1 <0> enter 2 <;> nextstate(main 2 -e:1) v 3 <$> const[IV 9] s 4 <#> gvsv[*c] s 5 <2> sassign vKS/2 6 <@> leave[1 ref] vKP/REFC -e syntax OK

    are identical (except for the code of constant.pm loaded in the first), while

    qwurx [shmem] ~ > perl -MO=Concise,-exec -e 'sub foo{"5"}; $c=4+foo;' 1 <0> enter 2 <;> nextstate(main 2 -e:1) v 3 <$> const[IV 4] s 4 <0> pushmark s 5 <#> gv[*foo] s 6 <1> entersub[t3] sKS/TARG,1 7 <2> add[t4] sK/2 8 <#> gvsv[*c] s 9 <2> sassign vKS/2 a <@> leave[1 ref] vKP/REFC -e syntax OK

    leaves the sub as a sub since it doesn't have a null prototype list.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      While I have no idea of Perl's internals, it also seems that it depends what the sub contains. Of course, this is logical, since you can't inline everything. Seems to be that things that can be reduced to constant values will be inlined, which also makes it easier to remember :) So, "4" will be inlined, "4+4" too, since it can also be optimized away. "@INC" won't, for example.


      Ordinary morality is for ordinary people. -- Aleister Crowley
Re^2: OOP - Constant Vs. Subroutine ()
by diotalevi (Canon) on May 13, 2007 at 03:59 UTC

    If you'd used constant instead of doing it manually and were also using perl 5.10, you'd also avoid the memory overhead for the function DoesNotChange. Anyone doing sub BAR () { FOO } won't get the optimization.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re^2: OOP - Constant Vs. Subroutine ()
by 2xlp (Sexton) on May 12, 2007 at 19:09 UTC

    agreed -- who cares. this in no way, shape, or form will noticably affect any sort of perl code.

    I just brought this topic up, because I wanted to understand exactly why the speed difference existed. all i really care for is being able to stash & access class variables. I find using subs/constants is much easier than using 'our' scoped package variables for stashing info -- its just a quick $self->name instead of inspecting the object and moving on from there

    In any event, I did the following benchmark below to test the speed difference between the various options in writing & calling these methods

    Results vary on each run, but fall into 2 general categories...

    faster:

    sub get() { 'a'; } use constant get_constant=> 'a';

    slower:

    sub get { 'a'; } sub get { return 'a'; } sub get() { return 'a'; }

    and the code...
    package class; use strict; sub new { my ( $proto )= @_; my $class= ref($proto) || $proto; my $self= bless ( {} , $class ); return $self; } sub get_sub { 'a'; } sub get_sub_nullproto () { 'a'; } sub get_sub_return { return 'a'; } sub get_sub_return_nullproto () { return 'a'; } use constant get_constant=> 'a'; package main; use strict; use Benchmark qw[ cmpthese ]; my $object= class->new(); cmpthese -1, { get_sub => sub { my $a= $object->get_sub; }, get_sub__paren => sub { my $a= $object->get_sub(); }, get_sub_nullproto => sub { my $a= $object->get_sub_nullproto; }, get_sub_nullproto__paren => sub { my $a= $object->get_sub_nullprot +o(); }, get_sub_return => sub { my $a= $object->get_sub_return; }, get_sub_return__paren => sub { my $a= $object->get_sub_return(); } +, get_sub_return_nullproto => sub { my $a= $object->get_sub_return_n +ullproto; }, get_sub_return_nullproto__paren => sub { my $a= $object->get_sub_r +eturn_nullproto(); }, get_constant => sub { my $a= $object->get_constant; }, get_constant__paren => sub { my $a= $object->get_constant(); }, };