SlideShare a Scribd company logo
2011.12.10 hiratara
d.hatena.ne.jp/hiratara

twitter.com/hiratara



Perl

YAPC   gihyo.jp
循環参照のはなし
my ($ref1, $ref2, $ref3);
        $ref1 = $ref2;
        $ref2 = $ref3;
        $ref3 = $ref1;



$ref1            $ref2              $ref3
GC

Perl   GC
mark-and-sweep GC
mark-and-sweep GC
mark-and-sweep GC
mark-and-sweep GC
reference counting
     1

              1



1
          1       2


                         1

          2       1
reference counting
     1

              0



1
          1       2


                         1

          2       1
reference counting
     1

              0



1
          0       1


                         1

          2       1
reference counting
     1

              0



1
          0       1


                         1

          1       1
reference counting
     1

              0



1
          0       1   Leak

                         1

          1       1
(1)

    Template::Plugin::Filter
    (TT-2.2)

    Template::Plugin


return $self->{ _STATIC_FILTER } ||= sub {
      $self->filter(shift);
};
(2)
    AnyEvent

my $t; $t = AE::timer 1, 0, sub {
   ...;
   undef $t;
};


            $t           sub { ... }
(2)
    AnyEvent

my $t; $t = AE::timer 1, 0, sub {
   ...;
   undef $t;
};


            $t           sub { ... }
(2)
    AnyEvent

my $t; $t = AE::timer 1, 0, sub {
   ...;
   undef $t;
};


            $t
(2)
    AnyEvent

my $t; $t = AE::timer 1, 0, sub {
   ...;
   undef $t;
};


            $t
(2)
    AnyEvent

my $t; $t = AE::timer 1, 0, sub {
   ...;
   undef $t;
};
(3)


my ($f, $x);
(sub { $f = sub { $x } })->();


                    OUTSIDE



     sub {...}            $f == sub { ... }
(3)
use Devel::Peek; Dump($f);

SV = IV(0x100827fd8) at 0x100827fe0
 REFCNT = 2
 RV = 0x100827878
 SV = PVCV(0x10082b5f8) at 0x100827878
   REFCNT = 1
   GVGV::GV = 0x100856bc0      "main" :: "__ANON__"
   OUTSIDE = 0x1008032a0 (ANON)
   SV = PVCV(0x100852a90) at 0x1008032a0
    REFCNT = 1
    GVGV::GV = 0x100856bc0     "main" :: "__ANON__"
    PADNAME = 0x1008277e8(0x100287000) PAD = 0x100827800(0x10025c0e0)
       1. 0x100827fe0<2> FAKE "$f" flags=0x0 index=1
5
(   ≒       )
1) ps
% perl
 for (1 .. 10000) {
    my $ref; $ref = $ref;

        warn `ps -o rss= -p $$` if $_ % 1000 == 0;
      }
      1272
      1304
      1328
      1352
      1376
...
2) Test::LeakTrace
use Test::LeakTrace;
no_leaks_ok { my $ref; $ref = $ref };
2) Test::LeakTrace
use Test::LeakTrace;
no_leaks_ok { my $ref; $ref = $ref };

               not ok 1 - leaks 1 <= 0
               # Failed test 'leaks 1 <= 0'
               # at - line 4.
               #     '1'
               #           <=
               #     '0'
               # leaked REF(0x10083b610) from - line 4.
               # SV = IV(0x10083b608) at 0x10083b610
               # REFCNT = 1
               # FLAGS = (PADMY,ROK)
               # RV = 0x10083b610
               #     SV = IV(0x10083b608) at 0x10083b610
               #         REFCNT = 1
               #         FLAGS = (PADMY,ROK)
               #         RV = 0x10083b610
               #           SV = IV(0x10083b608) at 0x10083b610
               #             REFCNT = 1
               #             FLAGS = (PADMY,ROK)
               #             RV = 0x10083b610
               #               SV = IV(0x10083b608) at 0x10083b610
               ...
3) Devel::Cycle
use Devel::Cycle;

my ($ref1, $ref2, $ref3);
$ref1 = $ref2;
$ref2 = sub { $ref3 };
$ref3 = [$ref1];

find_cycle($ref1);
Cycle (1):
                          $$A => &B
              $B variable $ref3 => $C
                          $$C => @D
                      $D->[0] => $A
4) Devel::Leak::Object
use Devel::Leak::Object qw{GLOBAL_bless};
$Devel::Leak::Object::TRACKSOURCELINES = 1;

my $ref; $ref = bless $ref => "XXX";

Tracked objects by class:
      XXX                               1

Sources of leaks:
XXX
    1 from - line: 3
5) DESTROY
sub Ref1::DESTROY { warn "destroyed REF1" }
sub Ref2::DESTROY { warn "destroyed REF2" }

my $x;
my $f = bless sub {
    $x;
    bless sub { $x } => "Ref2";
} => "Ref1";
$f->();

destroyed REF2 at - line 2.
destroyed REF1 at - line 1.
Devel::Gladiator



PASS (181) FAIL (436)
5
$self   sub { ... }
my $self = {name => "Hokkaido.pm", handler => undef};
$self->{handler} = sub {
   print "Hello, ", $self->{name}, ".n";
};

$self->{handler}->();




                                sub { ... }

       $self                   “Hokkaido.pm”
1)
my $self = {name => "Hokkaido.pm", handler => undef};
$self->{handler} = sub {
   print "Hello, ", $self->{name}, ".n";
   undef $self;
};

$self->{handler}->();



                                sub { ... }

       $self                   “Hokkaido.pm”
1)
my $self = {name => "Hokkaido.pm", handler => undef};
$self->{handler} = sub {
   print "Hello, ", $self->{name}, ".n";
   undef $self;
};

$self->{handler}->();



                                sub { ... }

       $self                   “Hokkaido.pm”
1)
my $self = {name => "Hokkaido.pm", handler => undef};
$self->{handler} = sub {
   print "Hello, ", $self->{name}, ".n";
   undef $self;
};

$self->{handler}->();



                                sub { ... }


                               “Hokkaido.pm”
1)
my $self = {name => "Hokkaido.pm", handler => undef};
$self->{handler} = sub {
   print "Hello, ", $self->{name}, ".n";
   undef $self;
};

$self->{handler}->();



                                sub { ... }


                               “Hokkaido.pm”
1)
my $self = {name => "Hokkaido.pm", handler => undef};
$self->{handler} = sub {
   print "Hello, ", $self->{name}, ".n";
   undef $self;
};

$self->{handler}->();
1)


(                   )



($self->{handler}       )
2) Scalar::Util::weaken
my $self = {name => "Hokkaido.pm", handler => undef};
Scalar::Util::weaken(my $weaken_self = $self);
$self->{handler} = sub {
   print "Hello, ", $weaken_self->{name}, ".n";
};

$self->{handler}->();


                                sub { ... }

       $self                   “Hokkaido.pm”
2) Scalar::Util::weaken



my $self = {name => "Hokkaido.pm", handler => undef};
Scalar::Util::weaken($self); #
$self->{handler} = sub {
   print "Hello, ", $self->{name}, ".n";
};

$self->{handler}->();
3)
my $self = {name => "Hokkaido.pm", handler => undef};
my $name = $self->{name};
$self->{handler} = sub {
   print "Hello, ", $name, ".n";
};

$self->{handler}->();


                                sub { ... }

       $self                   “Hokkaido.pm”
4)
my $self = {name => "Hokkaido.pm", handler => undef};
$self->{handler} = sub {
   my $self = shift;
   print "Hello, ", $self->{name}, ".n";
};

$self->{handler}->($self);



                                sub { ... }

       $self                   “Hokkaido.pm”
4)

AnyEvent::Handler




   $hdl->push_read (line => sub {
       my ($hdl, $line) = @_;
       ...
   });
5) Data::Decycle

use Data::Decycle;
my $guard = Data::Decycle->new(
    my $self = {name => "Hokkaido.pm", handler => undef}
);
$self->{handler} = sub {
    "Hello, ", $self->{name}, ".n";
};

$self->{handler}->();
5) Data::Decycle

dankogai

            guard

           1)
循環参照のはなし
:Perl 5.8.8


use Devel::Leak::Object qw{GLOBAL_bless};
bless my $x = {}, "Dummy";
(sub { sub { $x } })->();


Tracked objects by class:
      Dummy                                 1
:Perl 5.8.8


my $x = bless {}, "Dummy";
(sub { $x; sub { $x } })->();

my $x = bless {}, "Dummy";
(sub { my $x = $x; sub { warn $x } })->();
循環参照のはなし
:Obj-C              ARC

retain   release                Perl



CBRFuture *future = [[CBRFuture alloc] init];
__weak CBRFuture *weakenFuture = future;
leftHandle(self, ^(id e) {
    current = nil;
    leftSend(weakenFuture, e);
});
:Obj-C             Guard
NSString *local = @"OK";

static void changeLocalValue(BOOL willBreak) {
    id original = local;
    CBRGuard *guard = [[CBRGuard alloc] initGuard:^{
        local = original;
    }];

    local = @"LOCALVALUE1";
}
:Obj-C     Guard



   autorelease

More Related Content

循環参照のはなし

  • 4. my ($ref1, $ref2, $ref3); $ref1 = $ref2; $ref2 = $ref3; $ref3 = $ref1; $ref1 $ref2 $ref3
  • 5. GC Perl GC
  • 10. reference counting 1 1 1 1 2 1 2 1
  • 11. reference counting 1 0 1 1 2 1 2 1
  • 12. reference counting 1 0 1 0 1 1 2 1
  • 13. reference counting 1 0 1 0 1 1 1 1
  • 14. reference counting 1 0 1 0 1 Leak 1 1 1
  • 15. (1) Template::Plugin::Filter (TT-2.2) Template::Plugin return $self->{ _STATIC_FILTER } ||= sub { $self->filter(shift); };
  • 16. (2) AnyEvent my $t; $t = AE::timer 1, 0, sub { ...; undef $t; }; $t sub { ... }
  • 17. (2) AnyEvent my $t; $t = AE::timer 1, 0, sub { ...; undef $t; }; $t sub { ... }
  • 18. (2) AnyEvent my $t; $t = AE::timer 1, 0, sub { ...; undef $t; }; $t
  • 19. (2) AnyEvent my $t; $t = AE::timer 1, 0, sub { ...; undef $t; }; $t
  • 20. (2) AnyEvent my $t; $t = AE::timer 1, 0, sub { ...; undef $t; };
  • 21. (3) my ($f, $x); (sub { $f = sub { $x } })->(); OUTSIDE sub {...} $f == sub { ... }
  • 22. (3) use Devel::Peek; Dump($f); SV = IV(0x100827fd8) at 0x100827fe0 REFCNT = 2 RV = 0x100827878 SV = PVCV(0x10082b5f8) at 0x100827878 REFCNT = 1 GVGV::GV = 0x100856bc0 "main" :: "__ANON__" OUTSIDE = 0x1008032a0 (ANON) SV = PVCV(0x100852a90) at 0x1008032a0 REFCNT = 1 GVGV::GV = 0x100856bc0 "main" :: "__ANON__" PADNAME = 0x1008277e8(0x100287000) PAD = 0x100827800(0x10025c0e0) 1. 0x100827fe0<2> FAKE "$f" flags=0x0 index=1
  • 23. 5 ( ≒ )
  • 24. 1) ps % perl for (1 .. 10000) { my $ref; $ref = $ref; warn `ps -o rss= -p $$` if $_ % 1000 == 0; } 1272 1304 1328 1352 1376 ...
  • 26. 2) Test::LeakTrace use Test::LeakTrace; no_leaks_ok { my $ref; $ref = $ref }; not ok 1 - leaks 1 <= 0 # Failed test 'leaks 1 <= 0' # at - line 4. # '1' # <= # '0' # leaked REF(0x10083b610) from - line 4. # SV = IV(0x10083b608) at 0x10083b610 # REFCNT = 1 # FLAGS = (PADMY,ROK) # RV = 0x10083b610 # SV = IV(0x10083b608) at 0x10083b610 # REFCNT = 1 # FLAGS = (PADMY,ROK) # RV = 0x10083b610 # SV = IV(0x10083b608) at 0x10083b610 # REFCNT = 1 # FLAGS = (PADMY,ROK) # RV = 0x10083b610 # SV = IV(0x10083b608) at 0x10083b610 ...
  • 27. 3) Devel::Cycle use Devel::Cycle; my ($ref1, $ref2, $ref3); $ref1 = $ref2; $ref2 = sub { $ref3 }; $ref3 = [$ref1]; find_cycle($ref1); Cycle (1): $$A => &B $B variable $ref3 => $C $$C => @D $D->[0] => $A
  • 28. 4) Devel::Leak::Object use Devel::Leak::Object qw{GLOBAL_bless}; $Devel::Leak::Object::TRACKSOURCELINES = 1; my $ref; $ref = bless $ref => "XXX"; Tracked objects by class: XXX 1 Sources of leaks: XXX 1 from - line: 3
  • 29. 5) DESTROY sub Ref1::DESTROY { warn "destroyed REF1" } sub Ref2::DESTROY { warn "destroyed REF2" } my $x; my $f = bless sub { $x; bless sub { $x } => "Ref2"; } => "Ref1"; $f->(); destroyed REF2 at - line 2. destroyed REF1 at - line 1.
  • 31. 5
  • 32. $self sub { ... }
  • 33. my $self = {name => "Hokkaido.pm", handler => undef}; $self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; }; $self->{handler}->(); sub { ... } $self “Hokkaido.pm”
  • 34. 1) my $self = {name => "Hokkaido.pm", handler => undef}; $self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; undef $self; }; $self->{handler}->(); sub { ... } $self “Hokkaido.pm”
  • 35. 1) my $self = {name => "Hokkaido.pm", handler => undef}; $self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; undef $self; }; $self->{handler}->(); sub { ... } $self “Hokkaido.pm”
  • 36. 1) my $self = {name => "Hokkaido.pm", handler => undef}; $self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; undef $self; }; $self->{handler}->(); sub { ... } “Hokkaido.pm”
  • 37. 1) my $self = {name => "Hokkaido.pm", handler => undef}; $self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; undef $self; }; $self->{handler}->(); sub { ... } “Hokkaido.pm”
  • 38. 1) my $self = {name => "Hokkaido.pm", handler => undef}; $self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; undef $self; }; $self->{handler}->();
  • 39. 1) ( ) ($self->{handler} )
  • 40. 2) Scalar::Util::weaken my $self = {name => "Hokkaido.pm", handler => undef}; Scalar::Util::weaken(my $weaken_self = $self); $self->{handler} = sub { print "Hello, ", $weaken_self->{name}, ".n"; }; $self->{handler}->(); sub { ... } $self “Hokkaido.pm”
  • 41. 2) Scalar::Util::weaken my $self = {name => "Hokkaido.pm", handler => undef}; Scalar::Util::weaken($self); # $self->{handler} = sub { print "Hello, ", $self->{name}, ".n"; }; $self->{handler}->();
  • 42. 3) my $self = {name => "Hokkaido.pm", handler => undef}; my $name = $self->{name}; $self->{handler} = sub { print "Hello, ", $name, ".n"; }; $self->{handler}->(); sub { ... } $self “Hokkaido.pm”
  • 43. 4) my $self = {name => "Hokkaido.pm", handler => undef}; $self->{handler} = sub { my $self = shift; print "Hello, ", $self->{name}, ".n"; }; $self->{handler}->($self); sub { ... } $self “Hokkaido.pm”
  • 44. 4) AnyEvent::Handler $hdl->push_read (line => sub { my ($hdl, $line) = @_; ... });
  • 45. 5) Data::Decycle use Data::Decycle; my $guard = Data::Decycle->new( my $self = {name => "Hokkaido.pm", handler => undef} ); $self->{handler} = sub { "Hello, ", $self->{name}, ".n"; }; $self->{handler}->();
  • 48. :Perl 5.8.8 use Devel::Leak::Object qw{GLOBAL_bless}; bless my $x = {}, "Dummy"; (sub { sub { $x } })->(); Tracked objects by class: Dummy 1
  • 49. :Perl 5.8.8 my $x = bless {}, "Dummy"; (sub { $x; sub { $x } })->(); my $x = bless {}, "Dummy"; (sub { my $x = $x; sub { warn $x } })->();
  • 51. :Obj-C ARC retain release Perl CBRFuture *future = [[CBRFuture alloc] init]; __weak CBRFuture *weakenFuture = future; leftHandle(self, ^(id e) { current = nil; leftSend(weakenFuture, e); });
  • 52. :Obj-C Guard NSString *local = @"OK"; static void changeLocalValue(BOOL willBreak) { id original = local; CBRGuard *guard = [[CBRGuard alloc] initGuard:^{ local = original; }]; local = @"LOCALVALUE1"; }
  • 53. :Obj-C Guard autorelease

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. &amp;#x3010;5&amp;#x5206;&amp;#x3011;\n
  17. &amp;#x3010;5&amp;#x5206;&amp;#x3011;\n
  18. &amp;#x3010;5&amp;#x5206;&amp;#x3011;\n
  19. &amp;#x3010;5&amp;#x5206;&amp;#x3011;\n
  20. \n
  21. \n
  22. \n
  23. &amp;#x3088;&amp;#x3044;: &amp;#x30EA;&amp;#x30FC;&amp;#x30AF;&amp;#x3057;&amp;#x3066;&amp;#x308B;&amp;#x304B;&amp;#x306E;&amp;#x5224;&amp;#x5B9A;&amp;#x3068;&amp;#x3057;&amp;#x3066;&amp;#x306F;&amp;#x6027;&amp;#x683C;&amp;#x3001;&amp;#x308F;&amp;#x308B;&amp;#x3044;: &amp;#x539F;&amp;#x59CB;&amp;#x7684;&amp;#x3001;&amp;#x74B0;&amp;#x5883;&amp;#x4F9D;&amp;#x5B58;\n
  24. &amp;#x3088;&amp;#x3044;: &amp;#x30EA;&amp;#x30FC;&amp;#x30AF;&amp;#x5168;&amp;#x822C;&amp;#x3092;&amp;#x898B;&amp;#x3064;&amp;#x3051;&amp;#x3089;&amp;#x308C;&amp;#x308B;&amp;#x3001;&amp;#x308F;&amp;#x308B;&amp;#x3044;: &amp;#x7D50;&amp;#x679C;&amp;#x306E;&amp;#x8868;&amp;#x793A;&amp;#x304C;&amp;#x3054;&amp;#x3064;&amp;#x3044;\n
  25. &amp;#x3088;&amp;#x3044;: &amp;#x7D50;&amp;#x679C;&amp;#x304C;&amp;#x307F;&amp;#x3084;&amp;#x3059;&amp;#x3044;&amp;#x3001;&amp;#x3060;&amp;#x3081;: &amp;#x5FAA;&amp;#x74B0;&amp;#x53C2;&amp;#x7167;&amp;#x3092;&amp;#x63A2;&amp;#x3059;&amp;#x3060;&amp;#x3051;&amp;#x3002;XS&amp;#x306E;&amp;#x30EA;&amp;#x30FC;&amp;#x30AF;&amp;#x306F;&amp;#x691C;&amp;#x51FA;&amp;#x3067;&amp;#x304D;&amp;#x306A;&amp;#x3044;&amp;#x3002;OUTER&amp;#x7D61;&amp;#x307F;&amp;#x3082;&amp;#x7121;&amp;#x7406;&amp;#x307D;&amp;#x3002;\n\n
  26. &amp;#x3088;&amp;#x3044;: &amp;#x7C21;&amp;#x5358;&amp;#x306B;&amp;#x30EA;&amp;#x30FC;&amp;#x30AF;&amp;#x691C;&amp;#x51FA;&amp;#x3001; &amp;#x308F;&amp;#x308B;&amp;#x3044;: &amp;#x30AA;&amp;#x30D6;&amp;#x30B8;&amp;#x30A7;&amp;#x30AF;&amp;#x30C8;&amp;#x9650;&amp;#x5B9A;\n
  27. &amp;#x3010;10&amp;#x5206;&amp;#x3011;&amp;#x3088;&amp;#x3044;: &amp;#x89E3;&amp;#x653E;&amp;#x30BF;&amp;#x30A4;&amp;#x30DF;&amp;#x30F3;&amp;#x30B0;&amp;#x304C;&amp;#x6B63;&amp;#x78BA;&amp;#x306B;&amp;#x308F;&amp;#x304B;&amp;#x308B;(&amp;#x4E2D;&amp;#x306E;&amp;#x30AF;&amp;#x30ED;&amp;#x30FC;&amp;#x30B8;&amp;#x30E3;&amp;#x304B;&amp;#x3089;&amp;#x89E3;&amp;#x653E;&amp;#x3055;&amp;#x308C;&amp;#x308B;) &amp;#x308F;&amp;#x308B;&amp;#x3044;: &amp;#x3072;&amp;#x3069;&amp;#x3044;&amp;#x30CF;&amp;#x30C3;&amp;#x30AF;\n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. &amp;#x3010;15&amp;#x5206;&amp;#x3011;undef &amp;#x30A8;&amp;#x30E9;&amp;#x30FC;&amp;#x306E;&amp;#x539F;&amp;#x56E0;&amp;#x3068;&amp;#x306A;&amp;#x308B;&amp;#x3002;&amp;#x3053;&amp;#x306E;&amp;#x4F8B;&amp;#x3060;&amp;#x3068;&amp;#x30EA;&amp;#x30FC;&amp;#x30AF;&amp;#x3059;&amp;#x308B;&amp;#x3002;\n
  41. &amp;#x3053;&amp;#x306E;&amp;#x4F8B;&amp;#x3060;&amp;#x3068;&amp;#x3001;weaken&amp;#x3088;&amp;#x308A;&amp;#x3053;&amp;#x3061;&amp;#x3089;&amp;#x304C;&amp;#x81EA;&amp;#x7136;\n
  42. API&amp;#x3092;&amp;#x5909;&amp;#x66F4;&amp;#x3057;&amp;#x3001;&amp;#x30AF;&amp;#x30ED;&amp;#x30FC;&amp;#x30B8;&amp;#x30E3;&amp;#x3092;&amp;#x6E21;&amp;#x3055;&amp;#x305A;&amp;#x306B;&amp;#x3059;&amp;#x3080;&amp;#x3088;&amp;#x3046;&amp;#x306B;&amp;#x3059;&amp;#x308B;\n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. &amp;#x7532;&amp;#x6590;&amp;#x4E92;&amp;#x63DB;&amp;#x306E;&amp;#x305F;&amp;#x3081;&amp;#x306B;autorelease &amp;#x3067;&amp;#x8FD4;&amp;#x3057;&amp;#x3066;&amp;#x304F;&amp;#x308B;&amp;#x3053;&amp;#x3068;&amp;#x304C;&amp;#x3042;&amp;#x308B;&amp;#x304C;&amp;#x3001;&amp;#x305D;&amp;#x308C;&amp;#x3060;&amp;#x3068;&amp;#x3046;&amp;#x307E;&amp;#x304F;&amp;#x3044;&amp;#x304B;&amp;#x306A;&amp;#x3044;&amp;#x3002;&amp;#x4ED5;&amp;#x69D8;&amp;#x3092;&amp;#x3088;&amp;#x304F;&amp;#x8ABF;&amp;#x3079;&amp;#x308B;&amp;#x5FC5;&amp;#x8981;&amp;#x3042;&amp;#x308A;&amp;#x3002;\n
  52. \n