9 votes

Perl fuite de mémoire DBI

Je rencontre des problèmes de fuite de mémoire dans un script perl que j'exécute pendant de longues périodes, où la quantité de mémoire prise par perl continue d'augmenter. Pour cette raison, j'essaie d'utiliser Devel::Leak pour traquer la fuite. J'ai découvert que chaque fois que j'appelle la méthode prepare de DBI, le nombre de valeurs scalaires retournées par Devel::Leak augmente de un. Ci-dessous se trouve un script de test que j'ai concocté qui fait ce que je viens de décrire :

#!/usr/bin/perl
use strict;
use Devel::Leak;
use DBI;

START:
my $handle; # apparemment, cela ne doit être rien du tout
my $leaveCount = 0;
my $enterCount = Devel::Leak::NoteSV($handle);
print "ENTRER : $enterCount SVs\n";
{
    # VARIABLES DE CONFIGURATION
    my $platform = "mysql";
    my $database = "db";
    my $host = "localhost";
    my $port = "3306";
    my $user = "user";
    my $pw = "pass";

    # NOM DE LA SOURCE DE DONNÉES
    my $dsn = "dbi:mysql:$database:$host:3306";

    # CONNEXION PERL DBI
    my $dbh = DBI->connect($dsn, $user, $pw);
    $dbh->prepare("SELECT * FROM table"); # Le script semble gagner un SV sans cette
                                          # ligne ici, mais puisque c'est mon problème dans mon
                                          # script principal, j'ai décidé de la laisser
    # undef $dbh; J'ai essayé de le mettre à undefined, mais cela n'a pas fait de différence
}
$leaveCount = Devel::Leak::CheckSV($handle);
print "\nQUITTER : $leaveCount SVs\n";
sleep(1);
goto START;

Est-ce que j'ai commis une erreur ici, ou s'agit-il d'une fuite de mémoire dans le module DBI ? De plus, je sais qu'ajouter un SV à chaque tour de boucle n'est pas une grosse affaire, et que j'ai probablement des fuites de mémoire plus importantes ailleurs qui font que perl prend autant de mémoire du serveur. Cependant, j'aimerais quand même corriger cela si je le pouvais. Curiosité du programmeur :)

MISE À JOUR :

La première fois, il semble ajouter environ 3 000 SV, puis à chaque fois après, il augmente un à la fois.

5voto

ddoxey Points 880

Il y a une instance de DBI::dr (un hash béni) vivant à $DBI::lasth. Vérifiez la clé 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 "scalaire '$subpkg' => '$val'\n";
    }

    print Dumper( $DBI::lasth );

    $DBI::lasth->{ChildHandles} = []; # <-- réinitialiser la structure de données qui fuit

    my $leaveCount = Devel::Leak::CheckSV($handle);

    print "\nCOUNT: $enterCount to $leaveCount SVs\n";

    sleep(1);

    redo START;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X