Mercurial > pub > Impl
diff lib/IMPL/Profiler/Memory.pm @ 407:c6e90e02dd17 ref20150831
renamed Lib->lib
author | cin |
---|---|
date | Fri, 04 Sep 2015 19:40:23 +0300 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/IMPL/Profiler/Memory.pm Fri Sep 04 19:40:23 2015 +0300 @@ -0,0 +1,111 @@ +package IMPL::Profiler::Memory; + +use strict; +use Carp qw(longmess shortmess); +use Scalar::Util qw(refaddr weaken isweak); + +my %listeners; +my $trapped; + +BEGIN { + $trapped = 0; +} + +sub import { + if (not $trapped) { + *CORE::GLOBAL::bless = sub { + $_[1] |= caller unless $_[1]; + my $ref = CORE::bless $_[0],$_[1]; + + $_->track($ref) foreach values %listeners; + + return $ref; + }; + $trapped = 1; + } +} + +sub _ConnectListener { + my ($self,$listener) = @_; + + die "Invalid listener" unless ref $listener; + + $listeners{refaddr($listener)} = $listener; +} + +sub _RemoveListener { + my ($self,$listener) = @_; + + die "Invalid listener" unless ref $listener; + + delete $listeners{refaddr($listener)}; +} + +sub Monitor { + my ($self,$code) = @_; + + my $data = IMPL::Profiler::Memory::Data->new(); + + $data->Monitor($code); + + return $data; +} + +package IMPL::Profiler::Memory::Data; +use parent qw(IMPL::Object::Fields); + +use Data::Dumper(); +use Scalar::Util qw(refaddr weaken isweak); + +use fields qw( objects counter); + +sub CTOR { + my $this = shift; + $this->{objects} = []; + $this->{counter} = 0; +} + +sub track { + my $i = scalar @{$_[0]->{objects}}; + $_[0]->{objects}[$i] = $_[1]; + weaken($_[0]->{objects}[$i]); + $_[0]->{counter} ++; +} + +sub Purge { + my $this = shift; + + return $this->{objects} = [ grep defined($_), @{$this->{objects}}]; +} + +sub Dump { + my $this = shift; + return Data::Dumper->Dump([$this->{objects}]); +} + +sub isLeak { + my ($this) = @_; + $this->Purge(); + return ( scalar(@{$this->{objects}}) > 0); +} + +sub Monitor { + my ($this,$code) = @_; + + die "A reference to a subroutine is required" unless ref $code; + + IMPL::Profiler::Memory->_ConnectListener($this); + eval { + $code->(); + }; + my $err = $@; + IMPL::Profiler::Memory->_RemoveListener($this); + + die $err if $err; + + return; +} + + + +1;