jonswar / perl-mason

Mason 2
58 stars 20 forks source link

Major memory leak in Component and Request #3

Closed StephenClouse closed 13 years ago

StephenClouse commented 13 years ago

I traced down a massive memory leak in my Catalyst app today in part to Mason. The issue is caused by _orig_params in ::Component and _orig_request_params in ::Request. While the Moose attributes are appropriately marked as weak_ref, the copies made in BUILD are not and result in a memory cycle.

Cycle #1
    MC0::index_mc H->{_orig_params} => %I
    %I->{m} => Moose::Meta::Class::__ANON__::SERIAL::52 J
    Moose::Meta::Class::__ANON__::SERIAL::52 J->{orig_request_params} => %K
    %K->{interp} => Moose::Meta::Class::__ANON__::SERIAL::51 E
    Moose::Meta::Class::__ANON__::SERIAL::51 E->{match_request_path} => &F
    closure &F, $interp => $G
    $G => Moose::Meta::Class::__ANON__::SERIAL::51 E
Cycle #2
    MC0::index_mc H->{_orig_params} => %I
    %I->{m} => Moose::Meta::Class::__ANON__::SERIAL::52 J
    Moose::Meta::Class::__ANON__::SERIAL::52 J->{page} => MC0::index_mc H

In the case of running under Catalyst (with Catalyst::View::Mason2), it causes the component itself and the entire stash to leak on each request (as the stash contents are passed in as parameters).

This is a (very naive) patch to weaken the copies of the weak_ref parameters in BUILD. This fixed the issue for me.

jonswar commented 13 years ago

Thanks Stephen. Will look into this right away, and add a test to prevent similar future leaks.

On Jun 28, 2011, at 12:49 PM, StephenClouse wrote:

I traced down a massive memory leak in my Catalyst app today in part to Mason. The issue is caused by _orig_params in ::Component and _orig_request_params in ::Request. While the Moose attributes are appropriately marked as weak_ref, the copies made in BUILD are not and result in a memory cycle.

Cycle #1
   MC0::index_mc H->{_orig_params} => %I
   %I->{m} => Moose::Meta::Class::__ANON__::SERIAL::52 J
   Moose::Meta::Class::__ANON__::SERIAL::52 J->{orig_request_params} => %K
   %K->{interp} => Moose::Meta::Class::__ANON__::SERIAL::51 E
   Moose::Meta::Class::__ANON__::SERIAL::51 E->{match_request_path} => &F
   closure &F, $interp => $G
   $G => Moose::Meta::Class::__ANON__::SERIAL::51 E
Cycle #2
   MC0::index_mc H->{_orig_params} => %I
   %I->{m} => Moose::Meta::Class::__ANON__::SERIAL::52 J
   Moose::Meta::Class::__ANON__::SERIAL::52 J->{page} => MC0::index_mc H

In the case of running under Catalyst (with Catalyst::View::Mason2), it causes the component itself and the entire stash to leak on each request (as the stash contents are passed in as parameters).

This is a (very naive) patch to weaken the copies of the weak_ref parameters in BUILD. This fixed the issue for me.

Reply to this email directly or view it on GitHub: https://github.com/jonswar/perl-mason/pull/3

jonswar commented 13 years ago

(cc'ing mason-users)

The leaks you mention, as well as a few others I found, should be fixed in Mason 2.11 on its way to CPAN now. Let me know if it seems gone for you as well.

I have a test xt/author/leaks.t that confirms the absence of leaked objects, though it only tests one scenario; ideally I'll put in automatic leak detection around all tests.

Thanks for the heads up, Jon

On Jun 28, 2011, at 12:49 PM, StephenClouse wrote:

I traced down a massive memory leak in my Catalyst app today in part to Mason. The issue is caused by _orig_params in ::Component and _orig_request_params in ::Request. While the Moose attributes are appropriately marked as weak_ref, the copies made in BUILD are not and result in a memory cycle.

Cycle #1
   MC0::index_mc H->{_orig_params} => %I
   %I->{m} => Moose::Meta::Class::__ANON__::SERIAL::52 J
   Moose::Meta::Class::__ANON__::SERIAL::52 J->{orig_request_params} => %K
   %K->{interp} => Moose::Meta::Class::__ANON__::SERIAL::51 E
   Moose::Meta::Class::__ANON__::SERIAL::51 E->{match_request_path} => &F
   closure &F, $interp => $G
   $G => Moose::Meta::Class::__ANON__::SERIAL::51 E
Cycle #2
   MC0::index_mc H->{_orig_params} => %I
   %I->{m} => Moose::Meta::Class::__ANON__::SERIAL::52 J
   Moose::Meta::Class::__ANON__::SERIAL::52 J->{page} => MC0::index_mc H

In the case of running under Catalyst (with Catalyst::View::Mason2), it causes the component itself and the entire stash to leak on each request (as the stash contents are passed in as parameters).

This is a (very naive) patch to weaken the copies of the weak_ref parameters in BUILD. This fixed the issue for me.

Reply to this email directly or view it on GitHub: https://github.com/jonswar/perl-mason/pull/3

StephenClouse commented 13 years ago

I see no more leaks from Mason with 2.11.

jonswar commented 13 years ago

Cool, thanks again.

On Jul 1, 2011, at 11:01 AM, StephenClouse wrote:

I see no more leaks from Mason with 2.11.

Reply to this email directly or view it on GitHub: https://github.com/jonswar/perl-mason/pull/3#issuecomment-1485143