powerman has asked for the wisdom of the Perl Monks concerning the following question:

Any ideas why 'Errno' contants can be inlined but 'Socket' and 'Fcntl' constants can't?
use Benchmark qw( cmpthese ); use Errno qw( EAGAIN ); use Fcntl qw( O_NONBLOCK ); use Socket; # AF_INET BEGIN { our @const = qw( EAGAIN O_NONBLOCK AF_INET ); for my $const (@const) { eval "sub _$const () { ".&$const.' }'; die $@ if $@; } } our ($CONST_VALUE, $import, $inline, $scalar); for my $const (@const) { print "\n>>> Testing: $const\n"; $CONST_VALUE = &$const; cmpthese(5000000, { import => '$import = '.$const.';', inline => '$inline = _'.$const.';', scalar => '$scalar = $CONST_VALUE;', }); printf "Result: %d %d %d\n", $import, $inline, $scalar; } __END__ >>> Testing: EAGAIN Rate import scalar inline import 4716981/s -- -5% -19% scalar 4950495/s 5% -- -15% inline 5813953/s 23% 17% -- Result: 11 11 11 >>> Testing: O_NONBLOCK Rate import scalar inline import 904159/s -- -84% -84% scalar 5494505/s 508% -- -5% inline 5813953/s 543% 6% -- Result: 2048 2048 2048 >>> Testing: AF_INET Rate import inline scalar import 927644/s -- -84% -84% inline 5747126/s 520% -- -1% scalar 5813953/s 527% 1% -- Result: 2 2 2

Replies are listed 'Best First'.
Re: Slow constants
by BrowserUk (Patriarch) on Nov 02, 2005 at 14:07 UTC

    Update:Wrong! Please ignore content and downvote and see Perl Mouse's info below.

    Because Errno exports constant subs into the callers space, whereas the other two use AUTOLOAD to create the subs in their own package space and then &goto them...every time they are used.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      whereas the other two use AUTOLOAD to create the subs in their own package space and then &goto them...every time they are used.
      Eh, no. The first time they are used AUTOLOAD creates them and &gotos in them. The second time, the sub is there and the sub is called.

      The difference is that Errno defines all the subs at compile time - they are empty prototyped subs returning a single value - and are hence are being constant folded at compile time. If you use EAGAIN, Perl will substitute the appropriate value at compile time - which avoids all the overhead of calling a subroutine at run time.

      The benchmark is biased towards heavy use of constants. A typical program will only use a few constants, and only a few times in a program. That means that if you'd export a lot of constants the way Errno does, you pay a heavier price at compile time, regardless how often, and how many constants you use. Fcntl however avoids the costs of compiling all the subs you aren't going to use - but the price of using a constant goes up.

      Perl --((8:>*

        Doesn't the absence of an empty prototype in the assignment *$AUTOLOAD = sub { $val } mean that these are just normal (non-constant) subs, and will therefore never be inlined, and therefore, called everytime they are used?

        ## From Socket.pm (Fnctl.pm contains an nearly identical sub) sub AUTOLOAD { my($constname); ($constname = $AUTOLOAD) =~ s/.*:://; croak "&Socket::constant not defined" if $constname eq 'constant'; my ($error, $val) = constant($constname); if ($error) { croak $error; } *$AUTOLOAD = sub { $val }; goto &$AUTOLOAD; }

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        Thanks for your answers!
        Now it's time to meditate a little... :)