CC: | alex [...] flymine.org |
Subject: | Circular reference memory leak |
There is a circular reference loop in the XML::Rules parser objects that are created.
Creating an individual parser for thousands of objects caused a massive memory leak
in my case.
Here is the code I am using to test this:
use XML::Rules;
Show quoted text
Perl> my $parser = XML::Rules->new(rules => [_default => 'no content array']);
Here is the output of Devel::Peek: (as you can see, REFCNT on the main object is 2
upon creation)
RV(0xa2fe284) at 0xa2fe278
REFCNT = 2
FLAGS = (ROK)
RV = 0xa2fe318
SV = PVHV(0xa255af4) at 0xa2fe318
REFCNT = 7
FLAGS = (OBJECT,SHAREKEYS)
STASH = 0xa264f50 "XML::Rules"
ARRAY = 0xa2daa28 (0:11, 1:3, 2:1, 3:1)
hash quality = 71.9%
KEYS = 8
FILL = 5
MAX = 15
RITER = -1
EITER = 0x0
Elt "style" HASH = 0xa9473ab4
SV = PV(0xa21a388) at 0xa26e3b8
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0xa290080 "parser"\0
CUR = 6
LEN = 8
Elt "for_parser" HASH = 0xbd7fb0c4
SV = RV(0xa2fe394) at 0xa2fe388
REFCNT = 1
FLAGS = (ROK)
RV = 0xa2fe368
SV = PVHV(0xa255b08) at 0xa2fe368
REFCNT = 1
FLAGS = (SHAREKEYS)
ARRAY = 0x0
KEYS = 0
FILL = 0
MAX = 7
RITER = -1
EITER = 0x0
Elt "ignore_handlers" HASH = 0xbe1c1be5
SV = RV(0xa30d334) at 0xa30d328
REFCNT = 1
FLAGS = (ROK)
RV = 0xa30d2a8
SV = PVAV(0xa30d8ec) at 0xa30d2a8
REFCNT = 1
FLAGS = ()
ARRAY = 0xa2da9c8
FILL = 5
MAX = 5
ARYLEN = 0x0
FLAGS = (REAL)
Elt No. 0
SV = PV(0xa20d5a0) at 0xa30d2b8
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0xa26c828 "Start"\0
CUR = 5
LEN = 8
Elt No. 1
SV = RV(0xa30d2d4) at 0xa30d2c8
REFCNT = 1
FLAGS = (ROK)
RV = 0xa26ef48
Elt No. 2
SV = PV(0xa20d570) at 0xa30d2d8
REFCNT = 1
FLAGS = (POK,pPOK)
PV = 0xa290270 "Char"\0
CUR = 4
LEN = 8
Elt No. 3
SV = NULL(0x0) at 0xa30d2e8
REFCNT = 1
FLAGS = ()
Here is the output of Devel::Cycle:
Show quoted textPerl> find_cycle($parser);
Cycle (1):
$XML::Rules::A->{'ignore_handlers'} => \@B
$B->[1] => \&C
$C variable $self => \$D
$$D => \%XML::Rules::A
Cycle (2):
$XML::Rules::A->{'ignore_handlers'} => \@B
$B->[5] => \&E
$E variable $self => \$F
$$F => \%XML::Rules::A
Cycle (3):
$XML::Rules::A->{'normal_handlers'} => \@G
$G->[1] => \&H
$H variable $self => \$I
$$I => \%XML::Rules::A
Cycle (4):
$XML::Rules::A->{'normal_handlers'} => \@G
$G->[3] => \&J
$J variable $self => \$K
$$K => \%XML::Rules::A
Cycle (5):
$XML::Rules::A->{'normal_handlers'} => \@G
$G->[5] => \&L
$L variable $self => \$M
$$M => \%XML::Rules::A
Cycle (6):
$XML::Rules::A->{'normal_handlers'} => \@G
$G->[7] => \&N
$N variable $self => \$O
$$O => \%XML::Rules::A