Hi Stevan!

Thanks for your informative response. See below for mine.

On Sun, Jun 1, 2008 at 5:19 PM, Stevan Little
<[EMAIL PROTECTED]> wrote:
> Shlomi,
>
> On Jun 1, 2008, at 8:57 AM, Shlomi Fish wrote:
>>
>> I said that I'd like to convert Test-Run to Moose. Well, now I'm in
>> the midst of the translation - many tests fail, but the problem is
>> that the tests now run much more slowly. It is a noticable difference,
>> that makes running the tests unbearable.
>
> I have found that this is typical of sufficiently complex Class::Accessor
> modules, the coding style promoted by Class::Accessor seems to not match
> well with Moose. In particular where passing undef values into the accessors
> is concerned (which is almost certainly where your test failures are coming
> from) Moose will not allow this (a "Str" type is not "a string, but possibly
> undef too"). Also proper use of lazy & default/builder with Moose will help
> make instance generation quicker, especially in the cases where you don't
> always need every slot to be initialized. In those cases too, using the
> "predicate" option (documented in Class::MOP::Attribute) will help as well.
> Here is an example of this actually:
>
> Class::Accessor version:
>
>  {
>      package Foo;
>      __PACKAGE__->mk_accessors('bar');
>  }
>
>  my $foo = Foo->new; # no "bar" initialized
>  if ($foo->bar) { ... } # this check is cheap, because your just checking
> the accessor
>
> Moose version:
>
>  {
>      package Foo;
>      use Moose;
>
>      has 'bar' => (is => 'rw', lazy => 1, default => 'FOO::BAR', predicate
> => 'has_bar');
>  }
>
>  my $foo = Foo->new; # no "bar" initialized
>  if ($foo->bar) { ... } # this check is NOT cheap, because your forcing the
> deferred value in bar to be created
>  if ($foo->has_bar) { ... } # this check *is* cheap, because your just
> checking slot existence
>
> Now, in the above example thats not really that much of a difference, but if
> 'bar' were are large complex data structure or some expensively computed
> value, then it would make a huge difference.
>
> It should be pointed out that the most recent Moose/Class::MOP release has a
> speedup which showed approx. 20-25% better performance, so things are
> improving. And people have seen anything from a 3x to 10x times performance
> increase by making their classes immutable (depending largely on the
> complexity of the classes I think, no one has cared enough to benchmark and
> figure it out).
>

Very interesting.

>> The problem as I see it is that I'm using Plug-ins instead of Roles
>> and that I didn't finalise the class. Of course, I'd rather not
>> finalise the class, or ditch away plug-ins.
>
> I think perhaps you misunderstand the use of the "immutable" feature. First,
> it is not finalizing, in the C# sense of the word, where it prohibits
> subclassing and such. Making a class immutable means that the metaclass can
> longer be altered, it allows Moose to then create an inlined constructor as
> well as memoize several of the more commonly needed bits of data in the
> metaclass. This is much less restrictive then you might think, and unless
> you are doing lots of ->meta hacking, you will never need to care.

Actually, I only use "finalised" because I could not remember the
"immutable" term, and was too lazy to look it up. But I meant
immutability. I know that what immutability does is as you described,
but I don't want that, because I may still want to have further
plugins added to the class.

>
> I am not sure how you are doing plugins, but there are two ways to go about
> this in the Moose world utilizing roles.
>
> 1) Compile-time
>
> This is plugins that you can know about during class construction time, and
> are *class* specific. So you simply create your class, applying the roles
> for the plugins. Often times, this is enough and runtime pluggable-ness is
> really overkill and not actually necessary. The key thing about this is that
> it is *class* specific, meaning you will want several instances of a
> specific class (with a specific set of plugins applied to it) in your
> application.  This may require creating a few extra subclasses, but really
> if your application doesn't require arbitrary combinations of plugins
> applied to arbitrary instances of varying classes, then this may actually
> help increase the clarity of you design.
>
> Now, since this is all compile-time defined, obviously it does not hamper
> making a class immutable.

I actually may need to add plugins at run-time.

>
> 2) Run-time
>
> Now, sometimes your application design *does* require arbitrary combinations
> of plugins applied to arbitrary instances of varying classes, in this case
> you really do need a plugin system. In this case you can still use roles,
> you just apply them to an instance instead of to a class. Of course this is
> a more expensive operation because Moose needs to create an anon-class for
> you and apply the role to that, but you asked for it, and so you need to pay
> the cost. Moose will cache specific combinations of class+roles and try to
> reuse the anon-classes if possible, and it does help if you apply all the
> roles at once and not in succession.
>
> Now, even though this is all done at runtime, you can still make your
> underlying classes immutable and get some of the performance benefits it
> provides.
>

I see.

>
>> And naturally, Moose is
>> also making many run-time checks that are not present in my old
>> Class-Accessor and are not really necessary for me. As much as I
>> appreciate type-checking for instance members, I'm disciplined enough
>> for it not to matter much.
>
> So just remove the types, it is that simple since they are entirely
> optional. In fact, the accessor generated by Moose for this:
>
>  has foo => (is => 'rw');
>
> if *faster* the the typical Class::Accessor version since it never creates a
> lexical $self, and just uses $_[0] instead. Moose does as much as it can to
> only make you pay for the features you use, but it cannot remove the cost of
> features you use, but just don't really want ;)
>

Yes, but to me it seems that it beats the point of using Moose. If I'm
using Moose, I'd rather have type-checking, so people will know what
every class member is.

>> So Moose seems impressive, but an overkill for Test-Run's needs.
>
> I think perhaps you have not given Moose enough of a chance, and that your
> making this judgement before properly understanding what Moose can provide
> for you. Any powerful tool (like Moose), if not properly used, will seem
> like overkill.

Ah.

>
>> So unless Moose will become faster, I won't be able to use it in
>> Test-Run, and will have to rely on Class-Accessor and the additional
>> logic I've built on top of it.
>
> Moose is becoming faster and that is one of our primary goals right now.
> However in your case, by using type checks you don't want and not making
> your classes immutable, *you* are the one slowing your application down. The
> tools are right in front of you, you need only to use them.

OK.

>
>> From what I've heard of CPython, they
>> often re-implemented Python libraries code in C to make them faster.
>> Perhaps the Perl world should follow suit.
>
> We have some C/XS in Class::MOP and the inclusion of that it provided our
> last major speed boost actually. There are possibly a few other places we
> could recode in C/XS that would provide us some more benefits, but since I
> am not (and never will be) a C programmer, all I can say is
>
> ... patches welcome :)

Well, I'm a C programmer, but not much of a PerlXS programmer. I've
read "Extending and Embedding Perl"  (E&EP) once upon a time, but
forgot it, and found it a bit deficient. I also downloaded its PDF
from eDonkey, so I can use it as a reference. I also started writing

http://opensvn.csie.org/shlomif/documents/perl/trunk/perl5/ext-embed-internals/

But have neglected it. The core XS documentation is very
hard-to-understand. I'd love to be able to write XS properly some day,
but it will take some time.

-----------

Back to the topic: I still feel that Moose is a bit unsuitable for the
style of OO I used in Test-Run.

Regards,

         Shlomi Fish

Reply via email to