Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Efficiency and overhead of subs

by stillinger (Acolyte)
on Nov 16, 2001 at 08:50 UTC ( #125763=perlquestion: print w/replies, xml ) Need Help??

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

Hi. I'm newish to perl, (though not to programming), and am a real efficiency/small memory footprint freak.

In general, but specific to perl, what's the overhead and time-efficiency loss in using subroutines? I'm used to C and using lots of organizational subroutines and lean, tight 'main's. Is this not such a good idea when programming, say, CGI? Or is the loss pretty insignificant?

Thanks, Stillinger

Replies are listed 'Best First'.
Re: Efficiency and overhead of subs
by chromatic (Archbishop) on Nov 16, 2001 at 09:08 UTC
    There is overhead, and my understanding is that much of it is the stuff that happens when entering and leaving blocks. Subs count. A chunk of that is spent figuring out the correct lexical scope to use.

    You can get a decent idea with a benchmark like the following:

    use Benchmark; sub asub { for (1 .. 2000) {} } Benchmark::cmpthese (5000, { 'sub' => sub { asub() }, 'nosub' => sub { for (1 .. 2000) {} }, });
    With 5.6.1 on my Linux box, there's a 4% penalty for subroutines. With the latest development version, it's so close to 0% as to be statistically insignificant.

    I doubt you'll find many cases where using subroutines effectively outweighs the performance hit of loading a Perl interpreter and compiling your program in a CGI environment each time. Besides that, if you unroll subs enough, you'll probably ruin locality of reference.

    Perl's more about developer ease than efficiency/small memory footprint anyway. Sometimes that matters.

      As usual, it's already been done before as well. I asked this same question basically about 8 months ago I suppose. The discussion is over here at Fundamental Benchmarks. Hope this helps out!

Re: Efficiency and overhead of subs
by MZSanford (Curate) on Nov 16, 2001 at 15:20 UTC
    If the options are use a sub, or repeat the same code in each place, you will save nothing by avoiding the sub.

    Usaing a sub does require that all arguments are put on the stack, and then pulled off again (array opts on <code lang="perl">@_</code>). Not using a sub means the parser has to do that much more work. In a benchmark i did sometime ago, trying to recreate C pre-processor macro, i found the extra parsing time was much longer than the sub stack work.

    That aside, there is a way to minimize the main of the function call structure. When passing arrays and hashes, pass references. This makes a single RV (size of a scalar in effect) trasnfer as oposed to an entire array's worth of elements.

    Also, as much as i will optimize everything, there has to be a point , i have resently learned, where you figure you will be spending time waiting on the network and disks enough that the changes will not help. So, in short ...

    1. functions are marginally slow.
    2. use them anyway
    3. ob-fu for speed is no better, just un-maintainable

    my $cents = 2;
    i had a memory leak once, and it ruined my favorite shirt.
Re (tilly) 1: Efficiency and overhead of subs
by tilly (Archbishop) on Nov 16, 2001 at 19:18 UTC
    If you are into tight code that doesn't waste memory, then Perl is the wrong language for you.

    Perl code routinely takes of several times the space and runs at a small fraction of the speed of an equivalent C program. There is nothing you can do about that other than to take up a language whose philosophy on life more closely matches your own. And if you are programming a CGI, the overhead of starting Perl itself is likely to dwarf the puny effects of your modularizing your code (which is unfortunately not free, though it is pretty cheap).

    But that said, I strongly recommend that you read the chapter from Code Complete on Optimization. As he says there at length, when it comes to optimization, don't lose the forest for the trees. Concentrate on sane, understandable code. Don't worry about efficiency. And then in the time you save with good development practices, profile and optimize what needs to be optimized.

    Unless you are working on simple, fast code which has to work in embedded chips, and admittedly some do, this advice results in a better development balance, and on real projects is ironically likely to wind up with faster code than people who micro-optimize from the start.

    So if you have a real programming problem and Perl is a fit, then don't worry about overhead. Program sanely, try not to be stupid, pick decent algorithms, and when you are done, take Devel::DProf out for a spin if need be.

      Actually, you might want to spend more time thinking about how your perl will run, not how it's written. If you are writing a CGI, you can use mod_perl on apache, Perl for Isapi on IIS, etc...

      Also, I have found that using Perl2Exe can dramatically speed up a script that gets started often by eliminating the compile time.

      I guess the point is that within reason, programming practice has a lot less to do with efficiency than run time implementation. Welcome to the world of interpreted languages.

      That all said, use references, and avoid large hashes.


Re: Efficiency and overhead of subs
by jbert (Priest) on Nov 16, 2001 at 19:32 UTC
    Errr...then don't use perl. Every script you write will load a large, feature-rich interpreter and be recompiled every time - and all modules you use will also be loaded and recompiled on each invocation of your script (unless you use apache mod_perl, that is)

    Every integer you store (ok...not every one) will be represented internally as a complex 'scalar' structure which knows all about becoming a string, an object and a reference to other types of data.

    Not that perl code can't be fast and efficient, but memory footprint is pretty much always going to suck compared to any non-script language.

    Does this matter? Depends what you are doing

    Its always good to have fast, efficient code. But its better to have readable, correct code which (in the few places it matters) does clever, less obvious things.

    Less negatively, you can pack data compactly in perl using functions like pack and unpack. Function calls do have some overhead as in any language, but you could only notice that in a tight loop. There are various introspection options open to you if your perl was built with -DDEBUGGING and there are useful modules on CPAN in the Devel:: hierarchy for profiling.

    But my 2p is that general coding style should be optimised for readability, with the hairy bits confined to areas which measurements have shown to be performance critical (and then only if performance is an issue or you have time on your hands).

Re: Efficiency and overhead of subs
by orkysoft (Friar) on Nov 16, 2001 at 21:05 UTC

    I think you're asking the wrong question.

    Don't ask, 'How long does the computer take to run this program?'. Ask: 'How long do I take to write this program?'.

    You'll probably save hours of time and lots of coffee by writing the program in such a way that it's easier to maintain. Do a million milliseconds spent executing the program a million time really weigh up against the hours (one hour equals 3.6e+6 milliseconds) saved by writing it in an easier-to-maintain way, using subs?

    Besides, if you're still more concerned about CPU efficiency as opposed to programmer efficiency, you'd better stick to C :-)

      I'm not sure I would agree with this (throwing a bone in here to start another discussion). While I agree that one of the purposes of developing a program is to create it as lazily/quickly, readable/maintable as possible, a bigger purpose is to serve the end user of the program. While we're talking about microseconds, they can add up under exponential usage (such as IMDB using mod_perl instead of CGI scripts) and if the user can appreciate faster response times, I'm for taking more development time and serving that purpose.

      My argument only holds up in those special cases, though, where the usage is enormous - so I'd answer the original pos(t)er of the question with "It Depends" (the quintessential answer of Consultants everywhere ;)) and it depends on the usage of the program.

      And if you're talking about a totally different dev environment (C, Assembly, etc), where I'm not proficient in and would take significant research/dev to get proficient, Perl's good 'nuf for me (so that would be another exception to my argument ;)).


        I totally agree that it depends..Let me tell you why.

        I just finished a project that took a process that someone was doing by hand (going to a web site through a series of pages, copy, paste into excel...blah, blah) which took roughly 3-5 hours a day, and streamlined it down to a couple hundred lines of code that is a click-and-walk-away process of about 20-30 minutes. That's a savings on the order of 1x103% improvement in time.

        Now I could probably shave another 5-10% off of the remainder if I wanted to implement fork() in this windows2k world here in my office, but frankly, considering what they already have, I doubt the end-user is going to notice those last 2 minutes, and the headache wasn't worth it.

        When it comes to implementation, YMMV. Work where you're comfortable, and determine your trade-offs. re - Time and Effort vs. Return.

        Just my US$0.02 worth.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://125763]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (5)
As of 2019-12-08 23:23 GMT
Find Nodes?
    Voting Booth?

    No recent polls found