I wanted to build an awesome place for people to discuss module specific issues, but I don't have any more time for this, and there are much better places to discuss Perl-related issues. I'd recommend asking your question on Stack Overflow or on Perl Monks.
If you are looking for a Perl tutorial or Perl-related news, I hope these links will serve you well.
Posted on 2009-01-07 04:05:55-08 by jerome
Generating thousands of objects
I am getting to a point in a project using OIO where I'll need to generate and query lots of short-lived objects, with speed being a concern. I have yet to code that aspect of the project and I have been wondering how OIO is going to fare in that kind of situation. I was therefore very much interested in this use perl thread: http://use.perl.org/~hanekomu/journal/37775. I ran the same benchmark on my machine and added Object::InsideOut to the mix (see code below). I found that OIO performs at about the same level as Moose (the non-immutable version) unfortunately. I was wondering if you had seen this particular use perl thread (from last November) and had any comments. I am particularly intrigued by the 'immutable' option of Moose, is the concept applicable to OIO? Thanks Jerome
#!/usr/bin/env perl use warnings; use strict; use Benchmark qw(cmpthese timethese :hireswallclock); package WithMoose; use Moose; has myattr => ( is => 'rw' ); package WithMooseImmutable; use Moose; has myattr => ( is => 'rw' ); __PACKAGE__->meta->make_immutable; package WithObjectTiny; use Object::Tiny qw/myattr/; package WithObjectInsideOut; use Object::InsideOut;{ my @myattr :Field :Get('myattr') :Arg('myattr'); } package WithObjectInsideOutNoGen; use Object::InsideOut;{ my @myattr :Field; sub get_myattr { my ($self) = @_; return $myattr[$$self]; } sub set_myattr { my ($self,$value) = @_; $myattr[$$self] = $value; } } package main; cmpthese(timethese(100_000,{ moose => sub { my $obj = WithMoose->new(myattr => 27); my $x = $obj->myattr; }, moose_immutable => sub { my $obj = WithMooseImmutable->new(myattr => 27); my $x = $obj->myattr; }, object_insideout => sub { my $obj = WithObjectInsideOut->new(myattr => 27); my $x = $obj->myattr; }, object_insideout_no_gen => sub { my $obj = WithObjectInsideOutNoGen->new; $obj->set_myattr(27); my $x = $obj->get_myattr; }, object_tiny => sub { my $obj = WithObjectTiny->new(myattr => 27); my $x = $obj->myattr; }, direct_hash => sub { my $h = {}; $h->{myattr} = 27; my $x = $h->{myattr}; }, }));
On my laptop I get this:

$ perl accessors_benchmark.pl
Benchmark: timing 100000 iterations of direct_hash, moose, moose_immutable, object_insideout, object_insideout_no_gen, object_tiny...
direct_hash: 0.434398 wallclock secs ( 0.44 usr + 0.00 sys = 0.44 CPU) @ 229357.80/s (n=100000)
moose: 33.1195 wallclock secs (33.06 usr + 0.00 sys = 33.06 CPU) @ 3025.17/s (n=100000)
moose_immutable: 2.38401 wallclock secs ( 2.39 usr + 0.00 sys = 2.39 CPU) @ 41893.59/s (n=100000)
object_insideout: 32.2816 wallclock secs (32.18 usr + 0.00 sys = 32.18 CPU) @ 3107.23/s (n=100000)
object_insideout_no_gen: 20.8383 wallclock secs (20.70 usr + 0.02 sys = 20.72 CPU) @ 4826.95/s (n=100000)
object_tiny: 1.02048 wallclock secs ( 0.97 usr + 0.00 sys = 0.97 CPU) @ 103412.62/s (n=100000)
Direct Responses: 9667 | Write a response
Posted on 2009-01-07 12:39:30-08 by jdhedden in response to 9663
Re: Generating thousands of objects
While I have tried to optimize OIO whenever possible, the rapid generation and destruction of many objects is a bane for OIO. If the objects are trivial in nature, perhaps just using ordinary hash-based objects would make more sense. Another option might be to use a "recycling bin" for objects:
package MyClass; { use Object::InsideOut; my @myattr :Field :Std(myattr); # Class specific object recycling my @recycle_bin; sub GetObj { return (pop(@recycle_bin)) if (@recycle_bin); return MyClass->new(); } sub Recycle { push(@recycle_bin, shift); } } package main; MAIN: { # Get a new or recycled object my $obj = MyClass::GetObj(); # Initialize object $obj->set_myattr(27); # Use object print $obj->get_myattr(), "\n"; # Recycle object MyClass::Recycle($obj); }
The above limits object initialization, but doubtless it could be improved upon.

I cannot comment on Moose's immutable option because I do not know how Moose manages objects and their methods.
Direct Responses: 9675 | Write a response
Posted on 2009-01-07 19:07:22-08 by jerome in response to 9667
Re: Generating thousands of objects
Fair enough. I guess I was hoping that since you advertise speed as an argument for Object::InsideOut you would be curious as to how Moose achieves such a big leap in performance through immutability and see if something similar could be done to OIO :)

I gave make_immutable a glance and it looks like a mix of subroutine memoization and inlining of accessors and constructors. I didn't go as far as trying to figure out what exactly gave it the performance boost for the benchmark though. I did however run NYTProf on Object::InsideOut during the benchmark and came away with the impression that OIO was probably paying a non negligible price doing hash lookups in %GBL and copying the string $class around in various places. The subroutine 'is_sharing' also got flagged by NYTProf as time intensive. (Note that if you're interested in running NYTProf yourself, you'll have to replace a few 'goto' statements in InsideOut.pm as that is a limitation of NYTProf).

You're right though, for my needs I can probably simply revert to something simpler for my short-lived classes.
Direct Responses: 9699 | Write a response
Posted on 2009-01-11 16:47:08-08 by jerome in response to 9675
Re: Generating thousands of objects
Jerry, I have been thinking some more about the requirements for my project and I sure would like to be able to use Object::InsideOut for my short lived classes. I still need encapsulation and inheritance for example. So I spent more time with NYTProf and Object::InsideOut and would like to submit to you that the current sluggishness of OIO on object creation/deletion isn't necessarily a fact of life for some situations (like mine for example).

1. A large amount of time is spent in '_ID'. This may not be necessary when the users will only ever need one instance of the class at a time (as is my case). I suggest that OIO supports an additional class attribute on top of :public, :private, etc.. called something like ':singleton' to signal that particular usage of the class. Bypassing _ID improved object creation/deletion performance by 70% in my, albeit very simplistic, benchmark.

2. Most of the time left during 'new' is spent figuring out that nothings needs to be done. This is done for each object. I suggest that OIO supports another class attribute called ':inline' for example (and maybe a class method 'inline' also) that would radically change what happens during 'new'. Instead of checking every time what needs to be done, the 'new' subroutine would generate, stash and run a subroutine containing the minimum amount of code required for generating an object of the class. Such subroutine could be invalidated and regenerated if the user alters the class at runtime (by calling 'create_field' or 'add_class' for example). The user would incur a higher cost for the first object created for the class but additional objects may be much faster to generate (especially if their class is fairly simple) with no loss of functionality.

Does that sound right to you? Jerome
Direct Responses: 9708 | Write a response
Posted on 2009-01-12 14:08:01-08 by jdhedden in response to 9699
Re: Generating thousands of objects
The POD contains a simplistic scheme for a singleton class. As written, its main deficiency is that the singleton object isn't reinitialized if the "new" method is called with different parameters.

If the class is truly singleton in the way you described, you could override _ID with your own :ID subroutine:
sub _id :ID { return 0; }
Be aware that you must guarantee that object destruction occurs before you create another object of such a class. Otherwise, destruction of the old object will wipe out the data of the new object.

Customizing the "new" method for each class based on its needs is a nice idea. Thanks. I'll look into it, but it will take some work.
Direct Responses: 9710 | Write a response
Posted on 2009-01-12 20:19:35-08 by jdhedden in response to 9708
Re: Generating thousands of objects
I looked into trying to speed up the "new" method. While I could not come up with a way of cutting out functionality on a per class basis, I did implement a process of caching some information regarding object initialization activities on a per class basis. (However, the caching is minimal as you can see if you look at lib/Object/InsideOut.pm. and search for 'cache'.)

Jerome, please email me directly (email address is in the POD), and I'll send you a copy of what I've written for you to try. And if you look at the code and have any more ideas, I'd be happy to work on this further.
Direct Responses: 9726 | Write a response
Posted on 2009-01-13 20:03:08-08 by jerome in response to 9710
Re: Generating thousands of objects
Jerry, I sent you an email from my personal address yesterday. Let me know if you didn't get it. Jerome
Direct Responses: Write a response