Moose is a really impressive object system for Perl (mixins! traits! AOP! all optional fancy stuff!). MooseX::Declare is even more impressive, because it adds a clean Python/Ruby style syntax for methods, but also allows type checking. It’s pretty awesome. Though, there’s some perception that it’s slow. Is it?
(edit -- work in progress)
‘function’ above is a non-OO double loop that does something ‘remotely meaningful’. As you can see, moving to Perl OO makes it signficantly slower … but what’s amazing here is that MooseX::Declare or Moose does not really impose any additional cost to method calls. MooseX::Method::Signatures seems to totally suck, so we’ll throw it right out. But the other results — this is quite something. Note that this is without any type checking, but it shows that no additional cost is imposed. What about object initialization?
Moose new 6250/s MooseX::Declare new 83333/s normal perl OO new 200000/s
Here you see that there’s an obvious cost to Perl OO versus MooseX::Declare, but that’s blindingly fast. The relative speed is not important in the context of an application that does anything on top of this. The other interesting fact is that the much more desirable “MooseX::Declare” is actually faster than the regular Moose with regards to new. I haven’t determined why yet, but haven’t found the need to look — the better of the two alternatives came out on top. The next step is test the cost of the type checking with MooseX::Declare versus basic Perl OO untyped methods to see what that is.
One interesting find here is that if you use Moose and actually add the “package” keyword (which is unnecessary because the package name is the class name), they do get slower. Not sure why, but if you leave it out, the performance quickly falls in line with Perl OO norms. Also note all the tests are running non-trivial functions (just a couple of nested loops and a return) so that’s included in the test results. Given that Perl is known to be somewhat faster than a few other dynamic languages anyway, this is quite promising. The result is that Perl OO with Moose probably is probably on par with Python or Ruby, if not faster. The concern about overhead expressed in the Perl community really isn’t that serious at all.
Files used as a result of these tests can be found here. More likely to come, as well as examples of clever tricks that can be done with the library.
Update: combine “use MooseX::Declare;” with “use signatures;” and you loose some control over typing (and maybe some AOP), but “use signatures;” is exceedingly fast.
use MooseX::Declare;
class Foo extends Bar {
use signatures;
method new(...)
sub other_stuff(...)
...
}
It’s also very easy to use methods for when you need them, and to mix and match the two. What would be really nice though is if there was no time/speed penalty for using “method” when “method” specified no types. I’ll have to ping the author about that one.
Did you see Schwern’s comment on the same problem?
http://twitter.com/schwern/status/19952560416
.
Didn’t. That does default values and positionals better than “use signatures;”. Score. Thanks!
I’m still revising the tests, but Moose’s constructors seem quite reasonable — so remaining optimistic for now.
Ok, for me, Method::Signatures is currently about the same as MooseX::Method::Signatures when being used with MooseX::Declare.
However, using “use signatures” with MooseX::Declare is still ultra fast.
Odd. Workable though.
The speed difference you’re seeing between Moose and MX::Declare is because MX::Declare enables __PACKAGE__->meta->make_immutable by default and Moose does not. This causes a constructor to be generated and inlined into your class which is much faster than the multiple method calls the default Moose constructor uses.
I believe the current recommendation for speed is Method::Signatures::Simple when MooseX::Method::Signatures is too slow. The reason for the slowness is that Types are poorly optimized currently, but it has come up in conversations several time recently and some work may be done in that area soon.
Properly done, Moose’s significant overhead is in startup and memory. The runtime speeds in the benchmarks we’ve done have our accessors and what not are inline with equivalent hand-written perl accessors. It’s when you use more features (such as Type Signatures etc) that you start gaining more penalties. Enabling things like make_immutable significantly help the runtime performance too but penalize the startup performance.
Thanks for the write up though, I love hearing other people’s experiences!
-Chris
Excellent info, thanks! That’s incredibly helpful.
Yeah, I definitely don’t think types are critical, though I appreciate the feature mostly because it makes things more self documenting. This is still a huge win even if you have to use an extra signature module and
can’t use things that rely on Moose introspection. Definitely good to hear other people’s info!