While writing some code to track down a memory leak, I came up with the
following program using Moose 0.93. It appears to show a few leaks:
#!/usr/bin/env perl
use Modern::Perl;
use Devel::LeakGuard::Object qw( GLOBAL_bless );
use Devel::LeakGuard::Object::State;
my $leakstate;
BEGIN {
$leakstate = Devel::LeakGuard::Object::State->new(
on_leak => sub {
my $report = shift;
my @leaks = sort { $b->[1] <=> $a->[1] } # high refcount first
map { [ $_ => $report->{$_}[1] ] } # class, refcount
keys %$report;
printf "%-45s %s\n" => qw/Class Refcount/;
say "-" x 54;
foreach my $leak (@leaks) {
printf "%-50s %d\n" => @$leak;
}
}
);
}
{
package Foo;
use Moose;
has me => ( is => 'rw' );
}
{
package Bar;
use Moose;
has me => ( is => 'rw' );
}
{
package Baz;
sub new { bless {} => shift }
}
my $foo = Foo->new;
$foo->me($foo);
my $bar = Bar->new;
$bar->me($bar);
my $baz = Baz->new;
And the output:
Class Refcount
------------------------------------------------------
Class::MOP::Method::Accessor 221
Class::MOP::Attribute 112
Class::MOP::Method 48
Class::MOP::Class::Immutable::Class::MOP::Class 43
Class::MOP::Instance 32
Class::MOP::Method::Constructor 30
Moose::Meta::TypeConstraint 19
Class::MOP::Method::Wrapped 17
Class::MOP::Class 8
Moose::Meta::Method::Accessor 4
Moose::Meta::TypeConstraint::Parameterizable 3
Moose::Meta::Class 3
Moose::Meta::Attribute 3
Class::MOP::Package 2
Moose::Meta::TypeConstraint::Class 2
Moose::Meta::Instance 2
Bar 1
Config 1
Baz 1
Moose::Meta::TypeConstraint::Registry 1
Foo 1
Our actual application has some of those refcounts in the thousands (it gets
fun when I throw Catalyst and DBIx::Class into the mix). Am I just
misunderstanding this output or does Moose leak and Class::MOP leak? (I'm
suspicious because it shows that Baz still has a refcount of one).
Cheers,
Ovid
--
Buy the book - http://www.oreilly.com/catalog/perlhks/
Tech blog - http://use.perl.org/~Ovid/journal/
Twitter - http://twitter.com/OvidPerl
Official Perl 6 Wiki - http://www.perlfoundation.org/perl6