0

私は perl で簡単なことをしようとしていますが、それを行うのに苦労しています。mysql からデータを読み取り、データに対して何かを実行してから、何かを出力する必要があります。問題は、データベース ファイルのサイズが 90MB しかなく、システムのメモリが 4GB であることです。誰かがこの問題について私を助けてくれますか? つまり、それはなぜですか?

これが私のコードです:

#!/usr/bin/env perl
use common::sense;
use File::Slurp;
use Text::SpeedyFx;
use DBI;
use DBD::mysql;
my $dbh = DBI->connect('dbi:mysql:enron','x','y') or die "Connection Error:     $DBI::errstr\n";

# Create cascades
my $sql = "select uniqueid,mid,sender,receiver,unixdate,body,seen from     filteredmessage";
my $sth = $dbh->prepare($sql);
$sth->execute or die "SQL Error: $DBI::errstr\n";

# Variables
my $row; 
my $uniqueId;
my $msg1;
my $sender;
my $receiver;
my $unixdate;

my $uniqueId2;
my $msg2;
my $sender2;
my $receiver2;
my $unixdate2;
my $dif;
my $row2;
my $sql2;
my $sth2;
my $j;

my $i=1;
while ($row = $sth->fetchrow_hashref) {
    my $flagSingleRow = 0;
    $uniqueId = $row->{'uniqueid'};
    $msg1 = $row->{'body'};
    $sender = $row->{'sender'};
    $receiver = $row->{'receiver'};
    $unixdate = $row->{'unixdate'};

    $sql2 = "select uniqueid,mid,sender,receiver,unixdate,body,seen from filteredmessage";
    $sth2 = $dbh->prepare($sql2);
    $sth2->execute or die "SQL Error: $DBI::errstr\n";

    $j=1;
    while ($row2 = $sth2->fetchrow_hashref) {
        $uniqueId2 = $row2->{'uniqueid'};
        $msg2 = $row2->{'body'};
        $sender2 = $row2->{'sender'};
        $receiver2 = $row2->{'receiver'};
        $unixdate2 = $row2->{'unixdate'};

        $dif = cosine_similarity($sfx->hash_fv($msg1, 8192),$sfx->hash_fv($msg2, 8192));
        #if($dif>0.5){
            print $i." ".$j." ". $dif."\n";
        #}
        $j++;
    }
    $i++;
} 

sub cosine_similarity {
    my ($a, $b) = @_;

    my $nbits_a = unpack(q(%32b*) => $a);
    my $nbits_b = unpack(q(%32b*) => $b);

    return $nbits_a * $nbits_b
        ? unpack(q(%32b*) => $a & $b) / sqrt $nbits_a * $nbits_b
        : 0;
}
4

4 に答える 4

2

Text::SpeedyFx はひどくメモリ リークします。これは、同じものをハッシュするとメモリがどのように増加するかを示す簡単なデモです。

#! /usr/bin/perl

use v5.12;
use strict;
use warnings;

use Text::SpeedyFx;

my $sfx = Text::SpeedyFx->new;

for(1..1_000) {
    $sfx->hash_fv("12345", 8192);
}

say `ps auwx $$`;

for(1..10_000) {
    $sfx->hash_fv("12345", 8192);
}

say `ps auwx $$`;

for(1..100_000) {
    $sfx->hash_fv("12345", 8192);
}

say `ps auwx $$`;

for(1..1_000_000) {
    $sfx->hash_fv("12345", 8192);
}

say `ps auwx $$`;

$ perl ~/tmp/test.plx
USER      PID  %CPU %MEM      VSZ    RSS   TT  STAT STARTED      TIME COMMAND
schwern 81574  29.1  0.1  2463756   8412 s000  S+    1:58AM   0:00.21 perl /Users/schwern/tmp/test.plx

USER      PID  %CPU %MEM      VSZ    RSS   TT  STAT STARTED      TIME COMMAND
schwern 81574  54.4  0.2  2463756  18000 s000  S+    1:58AM   0:00.22 perl /Users/schwern/tmp/test.plx

USER      PID  %CPU %MEM      VSZ    RSS   TT  STAT STARTED      TIME COMMAND
schwern 81574  70.2  1.4  2553868 118384 s000  S+    1:58AM   0:00.35 perl /Users/schwern/tmp/test.plx

USER      PID  %CPU %MEM      VSZ    RSS   TT  STAT STARTED      TIME COMMAND
schwern 81574  98.5 13.4  3561496 1122320 s000  S+    1:58AM   0:01.49 perl /Users/schwern/tmp/test.plx

これは、hash_v への呼び出しごとに約 1K になります。1K はビット ベクトル サイズであるため、SpeedyFx が同じオクテットに対して同じスロットを再利用するのではなく、hash_v へのすべての呼び出しを個別に格納していることを示します。

これをバグとして報告しました。一方、問題を軽減するために、外側のループ内で Text::SpeedyFx オブジェクトを初期化できます。

于 2014-12-28T07:03:16.917 に答える
1

新しいクエリ$sth2->finishを再利用する前に呼び出してみてください。$sth2(例えば、

    }
    $sth2->finish;
    $i++;
}

)

また、私の 2 番目のコメントは、関数cosine_similarityが対称 (つまり、cosine_similarity(x,y) = cosine_similarity(y,x)) であるということです。したがって、 に を追加し、ORDER BY uniqueid$sql適切な変更を加え$sql2uniqueid >= $uniqueId.

于 2013-09-29T06:37:30.647 に答える