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

I've got a number of method calls that are 'getters' and 'setters'. I know that if I have a call that just returns a hash access, for instance, the compiler will optimize that function call away. Now, is there a way to do that with calls to functions I define in an eval? Would I have to put the eval in a BEGIN block to get those optimizations?

------
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.

  • Comment on Optimizing away calls to functions defined in eval

Replies are listed 'Best First'.
Re: Optimizing away calls to functions defined in eval
by suaveant (Parson) on Oct 16, 2001 at 17:41 UTC
    Have you thought about using closures instead of evals?

    Strangely enough about a week ago we were talking about auto-generating accessors and I still had the following code in my scratchpad... maybe it will help...

    package accessors; sub import { no strict 'refs'; my $pkg = (caller)[0]; for my $sub (@_) { *{$pkg.'::'.$sub} = sub { $#_ && $_[0]->{$sub} = $_[1]; $_[0]->{$s +ub} } } } package main; use accessors qw(foo bar baz);
    BTW - Is untested, but should give you the idea...
    Update ala demerphq, who pointed out $_[0] && would not set the accessor for false values... all fixed (update 2 change @_ to $#_... oops... tired still :)

                    - Ant
                    - Some of my best work - Fish Dinner

      So, instead of using eval, you're using typeglobs and closures. *ponders* What's the benefit here? Does this execute faster than using eval?

      (Sidenote: I know I'm usually the "Don't worry about faster" person, but since everything to solve my problem here is going to be arcane and unreadable-to-non-experts anyways, might as well go for speed. *grins*)

      ------
      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.

        It executes faster. Closures are compiled at (wait for it...) compile time. It uses less memory. Instead of making a new sub, it can point to the same code. All perl has to do is install a pointer in the symbol table and attach a new stash to the CV. The code is checked at compile time, not run time, so errors can be found and corrected.

        Besides that, string eval still has a few memory leaks, even in the latest versions of Perl. (That might change in the next week or two, but it doesn't help you right now.)

        Here's another thought. If you're generating these with an AUTOLOAD mechanism, you could potentially poison your method dispatch cache. That'll slow down the next method call. (Or I could be crazy... that sounds right, but I can't find it documented right now... sorry.)

        Update: It's in gv.c, specifically Perl_gv_fetchmeth. I've read scarier things, but don't ask for an annotation. ow! It's not available from user space, so there's no documentation. Modifying @ISA will mess with it, though.

        I am not sure about speed benefits, but in general I find that way easier to work with than evals, since you don't need to deal with the quoting and such. I'm not sure if it would help your optimization issues or not. I would guess that it is more efficient, but it might not be enough of a difference to notice :)

                        - Ant
                        - Some of my best work - Fish Dinner

        What you really want is to generate the subs before hand, from some resourcefile (XML works well). You can even have the seutp be part of the package

        sub getset_subs { return [qw/size height weight/]; }

        That can be used by the generator program to take the existing package and add a bunch of set/get subs to the end of it.

        This isn't perfect for all situations, you don't always know what you want before hand. But memory is cheap, IMO always calculate & produce code before hand if you can instead of producing the same structures at runtime again and again. Just make sure to keep the machine generated code machine generated. Editing machine generated code is a maintenance nightmare.

        -jackdied

Re: Optimizing away calls to functions defined in eval
by perrin (Chancellor) on Oct 16, 2001 at 17:08 UTC
    When you eval() something, aren't you just running the compiler? Seems like all the same optimizations should occur.

    When I build auto-accessors for use in mod_perl, I do it in a BEGIN so that they will be in shared memory.

      I've tried the BEGIN idea and it's not working. Could it be because I've got the evals in a function that is found through inheritance?

      ------
      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.

        By "not working", do you mean that the memory doesn't seem to be shared? If you're loading the module in your startup.pl and defining methods in a BEGIN, it should work. Or are you talking about something totally different?