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

Hi All,

I am santhosh, new member to this site. Very Glad to be a member of this site.

Currently I am handling a task of Performance Analysis and Tuning the PERL/Sybase scripts.

In the PERL code snippet,

- there is a loop in which a sub-routine is called

- this loop may be iterated many times ( approximately 10000 times ) So the sub-routine is also called that many times.

- Due to this sub-routine calling overhead I am loosing around 20% of time in execution
( I did a Benchmarking by keeping the code inline and without inline )

- The problem by keeping the code inline is, in the code snippet it is called twice, once inside the loop and once outside the loop, So it will be a Maintenance issue
( means in the future if i need to update anything related to this sub-routine part, i need to do it in both places if i make it as inline )

- Is there any way in PERL to resolve the above issue of Overhead

Please Advise
Thanks in Advance, Any help will be appreciated

Regards,
Santhosh

Replies are listed 'Best First'.
Re: Inline - Subroutine Overhead
by gaal (Parson) on Mar 01, 2005 at 21:02 UTC
    Welcome.

    10,000 times is not that much, in itself. Could it be that your subroutine has many parameters / return values? If so, simply rewriting it to pass by reference may speed things up considerably.

Re: Inline - Subroutine Overhead
by chromatic (Archbishop) on Mar 01, 2005 at 20:59 UTC

    Currently, there's no good way to inline subroutines. In the future it may be possible.

    If you can post part of the code, perhaps someone can suggest a way to do the same thing more efficiently.

    (By the way, it's Perl, never PERL.)

Re: Inline - Subroutine Overhead
by Limbic~Region (Chancellor) on Mar 01, 2005 at 21:21 UTC
Re: Inline - Subroutine Overhead
by dragonchild (Archbishop) on Mar 02, 2005 at 01:13 UTC

    WARNING - THIS SUGGESTION IS FRAUGHT WITH PERIL
    Use this at your own risk. I am not responsible if you get fired.

    You could unroll the function call stack (using goto and dynamic labels) and manipulate it yourself. This is ... very poor form, requires a book of comments, and is about as fragile as bone china. But, it is possible.

    Let's say you have:

    my $value = foo( 3, 4, 5 ); for ( 1 .. 10_000 ) { # Blahblah my $inside_value = foo( $_, 1, 2 ); # Yadda, yadda, yadda } my $other_value = foo( 7, 8, 9 ); sub foo { my ($first, @args) = @_; do_something( $first ); return do_something_else( @args ); }
    That looks to be roughly what you're doing, right? Well, you can transform that code as so:

    Note: I am not advocating this type of code nor am I suggesting that you won't be hunted down like the fool you are if you implement this code and quit the next day. I'm saying that you can inline functions in Perl that are called from outside the loop and here is how.

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Re: Inline - Subroutine Overhead
by BrowserUk (Patriarch) on Mar 02, 2005 at 11:22 UTC
    Is there any way in PERL to resolve the above issue

    You could always transfer the problem from runtime to compile time by using a source filter to provide an inline/macro facility. In use it would look something like this:

    #! perl -slw use strict; use Macro; MACRO sub fred { my( $a, $b, $c ) = @_; return ( $a + $b ) * $c; } ENDMACRO my( $x, $y, $z ) = ( 1, 4, 7 ); print fred( $x, $y, $z ); for my $x ( 1 .. 10 ) { print fred( $x, $y, $z ); } __END__ P:\test>435608 35 35 42 49 56 63 70 77 84 91 98

    And the actual code (whitespace reduced) that would be executed is:

    my( $x, $y, $z ) = ( 1, 4, 7 ); print do{ our $MACRO_RETURN; local $MACRO_RETURN; $MACRO_RETURN = ( $x + $y ) * $z; goto MACRO_RETURN;; MACRO_RETURN: $MACRO_RETURN }; for my $x ( 1 .. 10 ) { print do{ our $MACRO_RETURN; local $MACRO_RETURN; $MACRO_RETURN = ( $x + $y ) * $z; goto MACRO_RETURN;; MACRO_RETURN: $MACRO_RETURN }; }

    This is only a demonstration (with flaws) of the possibilities, and far from fully thought through, but it has some merits relative to the alternatives offered:

    The package Macro:

    package Macro; use strict; use warnings; use Filter::Simple; my %macros; FILTER_ONLY executable => sub { while( s[ MACRO\s+ sub\s+ (\w+)\s+ \{\s+ my\s*\( \s* ( [^\)]+? ) \s* \)\s* =\s* \@_;\s+ ( .*? ) \} \s* ENDMACRO ][]xsmg ) { my( $name, $args, $body ) = ( $1, $2, $3 ); $body =~ s[[\r\n]+][]g; $macros{ $name } = [ [ split ',\s*', $args ], "do{ our \$MACRO_RETURN; local \$MACRO_RETURN; $body; MACRO_RETURN: \$MACRO_RETURN }" ]; } for my $macro ( keys %macros ) { s[ $macro\( \s* ( [^\)]+ ) \s* \) ]{ my @actual = split '\s*,\s*', $1; my @formal = @{ $macros{ $macro }[ 0 ] }; my $do = $macros{ $macro }[ 1 ]; my %substs; @substs{ @formal } = @actual; $do =~ s[([\$][\w]+)]{ exists $substs{ $1 } ? $substs{ $1 } : $1 }eg; $do =~ s[return\s*(.*?)\s*;] [\$MACRO_RETURN = $1; goto MACRO_RETURN;]g; $do; }xeg; } $_; }; 1;

    Source filters are either condemned as evil, hailed as saviours, or sometimes both as people transition from one state of Perlish grace to another.


    Examine what is said, not who speaks.
    Silence betokens consent.
    Love the truth but pardon error.
Re: Inline - Subroutine Overhead
by mkirank (Chaplain) on Mar 02, 2005 at 08:36 UTC
    Welcome santhosh
    Quoting from the Programming Perl book
    There is overhead calling subroutines ,Especially when u pass lengthy parameter list or return lengthy values
    try passing values by reference, passing values as dynamically scoped globals, inlining the subroutine, or rewriting the whole loop in C