8

長時間実行している perl スクリプトで、メモリ リークの問題が発生しています。perl が占有するメモリの量が増え続けています。このため、 Devel::Leakを使用してリークを追跡しようとしています。DBIのメソッドを呼び出すたびにprepare、 によって返されるスカラー値の数がDevel::Leak1 ずつ増えることを発見しました。以下は、私が説明していることを実行する、まとめたテストスクリプトです。

#!/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 モジュールのメモリリークですか? また、ループのたびに 1 つの SV を追加することは大したことではなく、perl がサーバーのメモリを大量に消費する原因となっている別の場所でより大きなメモリ リークが発生している可能性が高いこともわかっています。とはいえ、できればこれも直したいところです。コーダーの好奇心:)

アップデート:

最初は 3,000 SV ほど追加されたようで、それ以降は 1 つずつ増えていきます。

4

1 に答える 1

5

$DBI::lasth に存在する DBI::dr (祝福されたハッシュ) のインスタンスがあります。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;
}
于 2012-12-02T04:54:48.070 に答える