http://qs321.pair.com?node_id=254860

Limbic~Region has asked for the wisdom of the Perl Monks concerning the following question:

All:
Calling a sub to do something takes just a little bit longer (microseconds I have been told) than if you copied and pasted the code in the sub and replaced the sub call with it. The difference is very small and for the sake of maintainability - it is worth the hit.

Beware premature optimization - dragons be hiding ahead.

Now I just happen to have be writing a script that reused the same 5 lines of code several times within a loop, so I made it a sub. This particular loop goes through millions of iterations. Now the difference in run times between using a sub versus copying and pasting the code was under 1 minute, but I wondered if there was a way to get the outcome of copying and pasting, but keep the maintainability of a sub.

I think in Perl 6 (I am oblivious), that you will be able to do just this (if the conditions are right). I asked in the CB and I got various suggestions. I was going to let it drop, but bart prompted me to post here if for no other reason than to have a node to Super Search on when someone else asks the same question.

The suggestions I have heard so far:

  • eval
  • Source Filter

    If someone knows how to do this without a lot of work - then please divulge. If there is no easy answer, then there is no need to pursue it. If you need that much speed - Perl probably isn't the right solution in the first place ;-)

    Cheers - L~R

  • Replies are listed 'Best First'.
    Re: Inline subs?
    by broquaint (Abbot) on May 02, 2003 at 01:12 UTC
      Dominus' Memoize is probably going to be the way to go, but here's a source filter implementation anyways
      package Inline::Subs; use strict; use Regexp::Common; use Filter::Simple; my $re = qr< sub ( [_a-zA-Z](?:[\w_]+) ) \s* : \s* inline \s* ( $RE{balanced}{-parens => '{}' ) >x; FILTER_ONLY code => sub { while(my($subname, $code) = /$re/) { s/$re// and s/\b$subname\b/$code/g; } } ; q[ and the rest is silence ];
      Brutish I know, but hopefully any subs declared sub funcname : inline will be inlined into the code. If not, that code (and the regexes from the Sub::Lexical source) should give you a head start :)
      HTH

      _________
      broquaint

        broquaint,
        Memoize was also mentioned in the CB, but would not help for my case:

        Do not memoize a function whose behavior depends on program state other than its own arguments, such as global variables, the time of day, or file input. These functions will not produce correct results when memoized.

        My millions of iterations were from file input. I will check your source filter out tomorrow to see if I can grok it - Thanks!

        L~R

        Why doesn't this already exist?

        ------
        We are the carpenters and bricklayers of the Information Age.

        Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

        Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

          Why doesn't this already exist?
          Because it's not as simple as it looks e.g
          sub foo : inline { my %args = @_; ... return $something; }
          This would require not just parsing out the sub but also the any munging of @_ and any exitting of the sub (e.g return, last etc). While I guess this could be done with a bit of op tree trickery or XS, a simple filter would only be suitable for dropping literal blocks of code (which would also have to comply with strictures). Having said that I probably will make a module, but with many, many disclaimers ;)
          HTH

          _________
          broquaint

    Re: Inline subs?
    by Joost (Canon) on May 02, 2003 at 12:20 UTC
      If you can fiddle your sub into a C preprocessor macro, you might want to take a look at the -P option in perlrun or Filter::cpp.

      Short intro from the docs

      -P NOTE: Use of -P is strongly discouraged because of its inh +erent problems, including poor portability. This option causes your program to be run through the C pr +eproces- sor before compilation by Perl. Because both comments and + cpp directives begin with the # character, you should avoid st +arting comments with any words recognized by the C preprocessor s +uch as "if", "else", or "define". If you're considering using "-P", you might also want to l +ook at the Filter::cpp module from CPAN.
      -- Joost downtime n. The period during which a system is error-free and immune from user input.
    Re: Inline subs?
    by PodMaster (Abbot) on May 02, 2003 at 07:15 UTC
      This particular loop goes through millions of iterations. Now the difference in run times between using a sub versus copying and pasting the code was under 1 minute,
      That doesn't really paint a picture.
      How long does a normal run take? 10 minutes? 2 minutes? 10 Hours?
      How long does the other one take? 9 minutes? 1 minute? 9 hours and 59 minutes?
      What's the percent difference? (       %10?       %50?       %0.16?)

      If the increase is %50, i'd say go for it (what broquaint showed).
      If it's %10 percent, maybe, but if it's 0.16? Forget it.


      MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
      I run a Win32 PPM repository for perl 5.6x+5.8x. I take requests.
      ** The Third rule of perl club is a statement of fact: pod is sexy.

    Re: Inline subs?
    by Improv (Pilgrim) on May 02, 2003 at 02:16 UTC
      Note that in certain circumstances, Perl will inline your code for you. See the perlsub manpage, looking for the phrase "Constant Functions". However, sadly, anything too complex won't be inlined automagically. Hope this helps..
    Re: Inline subs?
    by nadadogg (Acolyte) on May 02, 2003 at 18:44 UTC
      Just an idea from me, I'm still pretty low in the food chain in perl, but could you possibly write your sub as a very small module? That might speed things up a bit.

        Probably not. Subs can be slow because it's expensive to create, initialize, and enter a new lexical scope in Perl 5's internal stack-based system. Inlining is tricky because you still have to respect that lexical scoping -- and I doubt you'll get very much of a speed benefit because, in all but the simplest cases, you still have to pay the price of the ENTER/LEAVE ops.

        You'll avoid the cost of sub dispatch and you might have better code coherency (though it'll depend on where the stash is located), but I'm not convinced you'll see dramatic benefits.

        It'd probably be better to make ENTER/LEAVE faster than to treat the symptom.