<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
<meta name=Generator content="Microsoft Word 10 (filtered)">
<style>
<!--
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:12.0pt;
        font-family:"Times New Roman";}
a:link, span.MsoHyperlink
        {color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {color:purple;
        text-decoration:underline;}
span.EmailStyle17
        {font-family:Arial;
        color:windowtext;}
@page Section1
        {size:8.5in 11.0in;
        margin:1.0in 1.25in 1.0in 1.25in;}
div.Section1
        {page:Section1;}
-->
</style>
</head>
<body lang=EN-US link=blue vlink=purple>
<div class=Section1>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>I’ve found a memory leak in DBIx::Class that I’m
not really sure how to track down further. I’m hoping someone with
more familiarity with the internals can give me a pointer as to where to look.
Here are the particulars:</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>OS: NetBSD 3.0</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>DBIx: 0.05007</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>Sample program:</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>#!/usr/pkg/bin/perl -w</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>use lib "/home/alanh/birdweb/trunk/BirdWeb-Admin/lib";</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>use BirdWeb::Admin;</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>my $staging = "BirdWeb::Admin::Model::Production";</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>#my $staging = "BirdWeb::Admin::Model::Staging";</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> </span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>my $res = $staging->resultset('Birds')->search({id
=> { '>' => 450} } );</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>my $counter =1;</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>my $count = $res->count();</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>while ( my $row = $res->next ) {</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> print "\t$count\t".$counter++.
"\n";</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> print $row->default_bird_common_name_id->bird_common_name
. "\n";</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>}</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>warn "end of program\n";</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>With the DBI TraceLevel set to 1 here’s the relevant
part of the stderr output:</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- FETCH('Driver')= DBI::dr=HASH(0x8fb1294)
at Limit.pm line 301</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- FETCH('Driver')= DBI::dr=HASH(0x8fb1294)
at Limit.pm line 338</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- FETCH('Active')= 1 at DBI.pm
line 276</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- ping= 1 at DBI.pm line 276</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- prepare_cached('SELECT me.id,
me.bird_id, me.bird_common_name, me.common_name_notes FROM bird_common_names me
WHERE ( ( ( me.id = ? ) ) )' HASH(0x91824c0) ...)= DBI::st=HASH(0x96e8af8) at DBI.pm
line 448</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- execute('450')= 1 at DBI.pm
line 386</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- fetchrow_array= ( '450'
'484' 'Painted Bunting' undef ) [4 items] row1 at Cursor.pm line 36</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- FETCH('Active')= 1 at Cursor.pm
line 66</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- finish= 1 at Cursor.pm line
66</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>end of program</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(96e8af8))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(95cefd8))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(964d774))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::db=HASH(9679f54))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>Notice that the statement handles aren’t destroyed
until after the end of the program. The first one in the list should have
been destroyed at the bottom of the while loop (before “end of program”
was output).</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>Why does this matter? It depends on the DBI driver you’re
using. In the example above the MySQL driver is used and it reuses the
statement handle. The same program executed against a MSSQL database
using the Sybase driver has stderr output that looks like this:</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- FETCH('Driver')= DBI::dr=HASH(0x8fb1294)
at Limit.pm line 301</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- FETCH('Driver')= DBI::dr=HASH(0x8fb1294)
at Limit.pm line 338</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- FETCH('Active')= 1 at DBI.pm
line 276</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- ping= 1 at DBI.pm line 276</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- quote(450)= ''450'' at NoBindStorage.pm
line 18</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- FETCH('Active')= 1 at DBI.pm
line 276</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- ping= 1 at DBI.pm line 276</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- prepare_cached('SELECT me.id,
me.bird_id, me.bird_common_name, me.common_name_notes FROM bird_common_names me
WHERE ( ( ( me.id = '450' ) ) )' HASH(0x9768cfc) ...)= DBI::st=HASH(0x98738c4)
at DBI.pm line </span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>448</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- execute= -1 at NoBindStorage.pm
line 31</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- fetchrow_array= ( 450 484
'Painted Bunting' undef ) [4 items] row1 at Cursor.pm line 36</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- FETCH('Active')= 1 at Cursor.pm
line 66</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'> <- finish= 1 at Cursor.pm line
66</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>end of program</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9873534))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(98730c0))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9873618))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(98731a4))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(98736fc))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9873288))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(98737e0))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(987336c))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(98738c4))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9873450))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768510))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(976809c))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(97685f4))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768180))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(97686d8))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768264))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(97687bc))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768348))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(97688a0))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(976842c))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768984))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768a68))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768b4c))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768c30))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768d14))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768df8))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768edc))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9768fc0))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9743f9c))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9750678))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(9683d2c))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::st=HASH(963ee40))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face="Courier New"><span style='font-size:10.0pt;
font-family:"Courier New"'>! <- DESTROY(DBI::db=HASH(967fe1c))= undef
during global destruction</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>As you can see, that driver doesn’t reuse the
statement handle and memory is leaked.</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>I looked at the Cursor.pm code and it looks like pains are
taken to try and delete the statement handle, but clearly something is
maintaining a reference to it.</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>Anybody have any ideas? This leak makes it impossible
to use DBIx::Class for batch operations against my production database.</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>Thank you!</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'>- Alan</span></font></p>
<p class=MsoNormal><font size=2 face=Arial><span style='font-size:10.0pt;
font-family:Arial'> </span></font></p>
</div>
</body>
</html>