Method::Signatures returns! 5.12, func() and fast!

schwern on 2010-07-31T00:49:55

Chip submitted a minor performance patch to Method::Signatures today. That drove me to push out a new release making it friendly to 5.12 and adding func() for non methods!

func hello(:$greeting = "Hello", :$place = "World") { print "$greeting, $place!\n"; }

hello( place => "Earth" );

For those who don't know, one of the neato features of Method::Signatures is that it can alias references to make working with references less of a trial:

func popn(\@array, $howmany) { return splice @array, -$howmany; }

my @stuff = (1,2,3,4,5); my @last_three = popn(\@stuff, 3); # 3,4,5 print @last_three;

It does this with the amazing Data::Alias module. Unfortunately, 5.12 broke its black magic and its non-trivial to fix. Method::Signatures now makes Devel::Alias an optional dependency. If its available, it'll use it. Otherwise, no aliasing for you.

But that's ok, because perl5i makes working with references enjoyable. And while perl5i is adding its own simple signatures, they're forward compatible with Method::Signatures! They play together, so if you want perl5i and the full power of Method::Signatures you can have them.

use perl5i::2; use Method::Signatures;

func echo($message is ro) { say $message; }

Just make sure you load MS after perl5i. The last one loaded wins.

Finally, I was comparing Method::Signatures with MooseX::Method::Signatures and made a disturbing discovery. I always new MooseX::Method::Signatures would have a performance penalty, it does more checks than Method::Signatures, I just didn't realize how bad it was.

Here's comparing an empty signature: method foo() {}.

         Rate    MMS     MS    Std
MMS    3207/s     --  -100%  -100%
MS  1498875/s 46644%     --    -1%
Std 1508351/s 46940%     1%     --


That's showing MooseX::Method::Signatures is 450x slower than either Method::Signatures or a normal method call creaking out a mere 3500 method calls per second as compared to the 1.5 million it should be doing. And that's for a method with an empty signature!

To be clear, that's the speed of calling a method, not compiling them.

Here's one comparing a simple signature that requires a check, so MS can't optimize it away: method foo($arg!) { return $arg + 1 } That's a required positional argument.

         Rate    MMS     MS    Std
MMS    2928/s     --  -100%  -100%
MS   983127/s 33481%     --    -2%
Std 1005357/s 34240%     2%     --


3000 method calls instead of a million.

Now I'm the first to counter arguments bemoaning method call overhead. Usually it doesn't matter. Usually the extra cost of calling a method and checking arguments is insignificant compared to what that method actually does. And MooseX::Method::Signatures has features Method::Signatures does not, most significantly type checking. But my god! Three orders of magnitude of performance lost! And its not even using the extra MMS features. That's just too much.