Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Optimizing non-alphanumeric method calls

by trizen (Hermit)
on Sep 27, 2015 at 18:19 UTC ( [id://1143159]=perlquestion: print w/replies, xml ) Need Help??

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

Hello dear Perl Monks,

I'm asking for help because I have a very delicate problem which involves objects and method calls. More specifically, it involves calling methods which have punctuation marks in their names, such as "+", "-", etc...

So far, I tried 5 different ways for making a method call, but all turned out to be much slower than specifying directly the method name (using Perl-5.22.0).

use Benchmark qw(cmpthese); package Example { sub new { bless {}, __PACKAGE__ } sub method { } } my $obj = Example->new; my $meth = 'method'; cmpthese(-1, { direct => sub { $obj->method }, var => sub { $obj->$meth }, ref => sub { $obj->${\'method'} }, can => sub { $obj->can('method')->($obj) }, magic => sub { ${ref($obj) . '::'}{'method'}->($obj) }, } );

(I used "method" for the method name just for illustration, but consider that "method" can have any possible name)

Output:

Rate magic can ref var direct magic 3495252/s -- -0% -37% -41% -58% can 3510857/s 0% -- -36% -40% -58% ref 5518821/s 58% 57% -- -6% -34% var 5887725/s 68% 68% 7% -- -29% direct 8340945/s 139% 138% 51% 42% --

(If you are wondering where do I need this; well, it's part of a toy-compiler which generates Perl code from a much higher language, in which any operation is translated into a method call)

My question now is, how can I make the Perl interpreter to optimize non-alphanumeric method calls, in the same way as it optimizes direct alphanumeric ones?

Thank you.

Replies are listed 'Best First'.
Re: Optimizing non-alphanumeric method calls (any!)
by tye (Sage) on Sep 27, 2015 at 20:33 UTC
    Rate magic 3495252/s can 3510857/s ref 5518821/s var 5887725/s direct 8340945/s

    Those are all such tiny operations with such close rates that it would be almost impossible to implement a practical script where any of those approaches resulted in an even noticeable difference in total performance.

    Use whichever makes the code clearer.

    - tye        

Re: Optimizing non-alphanumeric method calls
by LanX (Saint) on Sep 27, 2015 at 18:33 UTC
    Well you asked for non alphanumeric method names but only showed benchmarks and code for normal method names.

    It's hard to tell what you really need.

    2 ideas

    1. You didn't try the option $obj->$c_method with $c_method being a code ref. ( that's what can() returns ) ... this should be fastest after a caching phase along with direct.

    2. If your method names are automatically generated try to convert non identifier into some kind of translation.

    Have a look at control characters like ^c and so on.

    Perl allows them for variables, maybe for method names too?

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

      Thanks for your reply.

      $obj->$c_method is indeed faster, but it cannot be used, unfortunately, on chained method calls, such as $obj->$method_1->$method_2, unless the result returned by $obj->$method_1 is stored somewhere, which I guess it may slow things down quite a bit.

      Regarding your second idea, I haven't tried control characters as method names yet, but it's a good idea. However, I'm not sure how safe it is to rely on this behavior as it may get deprecated in the future and forbidden by Perl (assuming that it currently works).

        >  but it cannot be used, unfortunately, on chained method calls, such as $obj->$method_1->$method_2, unless the result returned by $obj->$method_1 is stored somewhere, which I guess it may slow things down quite a bit. 

        I'm not sure what you mean, $c_method isn't different in this respect to the other approaches you have proposed.

        For chained method calls you need to return the object in intermediate calls, no matter which approach you use.

        Maybe you should show us some real code to make things clearer.

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

Re: Optimizing non-alphanumeric method calls
by Anonymous Monk on Sep 27, 2015 at 18:36 UTC

    Is this an option?

    my $can = $obj->can('method'); cmpthese(-1, { direct => sub { $obj->method }, can2 => sub { $can->($obj) }, } ); __END__ Rate direct can2 direct 15259941/s -- -21% can2 19276812/s 26% --

      It could be in some places, but not in all of them, such as when a method is called on the result returned by an expression.

      Thanks though, I will consider this a special optimization.

        Should be noted that it's equivalent to writing $obj->$can() (what I called $c_method )

        Benchmarks shouldn't change.

        update

        I think a 3% penalty is an affordable prize for clarity and easier chaining. (actually it's ignorable, Benchmark isn't that exact)

        $ perl use Benchmark qw(cmpthese); package Example { sub new { bless {}, __PACKAGE__ } sub method { } } my $obj = Example->new; my $meth = 'method'; my $can = $obj->can('method'); cmpthese(-1, { direct => sub { $obj->method }, can2 => sub { $can->($obj) }, can3 => sub { $obj->$can() }, } ); __END__ Rate direct can3 can2 direct 893673/s -- -24% -26% can3 1180322/s 32% -- -3% can2 1214700/s 36% 3% --

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

Re: Optimizing non-alphanumeric method calls
by Anonymous Monk on Sep 28, 2015 at 02:01 UTC
    I would keep things very simple ... don't get fancy-pants about it to shave a few microsecs. Map the "method-names" that you receive, in all their non-alphanumeric glory, to a corresponding closure, using a simple hashref. Perl should have to resolve the method-name only one time ... when constructing the closure ... such that control passes directly to the target routine.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1143159]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (4)
As of 2024-04-19 03:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found