我在perl脚本中遇到了一些内存泄漏问题,我正在运行很长一段时间,其中perl占用的内存量正在不断增长。因此,我尝试使用Devel::Leak来追踪泄漏。我发现每当我调用DBI的prepare
方法时,Devel::Leak
返回的标量值的数量就会增加一个。下面是我编写的测试脚本,它正在完成我正在描述的内容:
#!/usr/bin/perl
use strict;
use Devel::Leak;
use DBI;
START:
my $handle; # apparently this doesn't need to be anything at all
my $leaveCount = 0;
my $enterCount = Devel::Leak::NoteSV($handle);
print "ENTER: $enterCount SVs\n";
{
# CONFIG VARIABLES
my $platform = "mysql";
my $database = "db";
my $host = "localhost";
my $port = "3306";
my $user = "user";
my $pw = "pass";
#DATA SOURCE NAME
my $dsn = "dbi:mysql:$database:$host:3306";
# PERL DBI CONNECT
my $dbh = DBI->connect($dsn, $user, $pw);
$dbh->prepare("SELECT * FROM table"); # The script seems to gain one SV without this
# line here, but since this is my issue in my
# main script I decided to leave it in
# undef $dbh; I tried undef-ing this, but it made no difference
}
$leaveCount = Devel::Leak::CheckSV($handle);
print "\nLEAVE: $leaveCount SVs\n";
sleep(1);
goto START;
那么我在这里做错了什么,或者这是DBI模块中的内存泄漏?另外,我知道每次在循环中添加一个SV并不是一个大问题,并且我很可能在其他地方有更大的内存泄漏,导致perl占用服务器的大量内存。但是,如果可以的话,我还是想解决这个问题。编码器的好奇心:))
更新:
第一次通过它似乎增加了大约3,000个SV,然后每次增加它一次增加1个。
答案 0 :(得分:5)
有一个DBI :: dr(一个有福的哈希)的实例,它位于$ DBI :: lasth。查看ChildHandles密钥。
#!/usr/bin/perl
use strict;
use warnings;
use Devel::Leak;
use Data::Dumper;
use Symbol::Table;
use DBI;
START:
{
my $handle;
my $enterCount = Devel::Leak::NoteSV($handle);
DB:
{
my $platform = "mysql";
my $database = "db";
my $host = "localhost";
my $port = "3306";
my $user = "user";
my $pw = "pass";
my $dsn = "dbi:mysql:$database:$host:3306";
my $dbh = DBI->connect( $dsn, $user, $pw );
$dbh->prepare("SELECT * FROM table");
$dbh->disconnect();
}
my $st = Symbol::Table->New( 'SCALAR', 'DBI' );
for my $subpkg ( keys %{ $st } ) {
my $val;
{
my $var = "DBI::${subpkg}";
no strict 'refs';
$val = ${$var};
}
print "scalar '$subpkg' => '$val'\n";
}
print Dumper( $DBI::lasth );
$DBI::lasth->{ChildHandles} = []; # <-- reset leaking data structure
my $leaveCount = Devel::Leak::CheckSV($handle);
print "\nCOUNT: $enterCount to $leaveCount SVs\n";
sleep(1);
redo START;
}