我正在尝试用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;
}
答案 0 :(得分: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的每个调用,而不是为相同的八位字节重用相同的时隙。
我有reported this as a bug。同时,为了缓解这个问题,你可以初始化外部循环中的Text :: SpeedyFx对象。
答案 1 :(得分:1)
在重新使用$sth2->finish
新查询之前,请尝试调用$sth2
。 (例如,
}
$sth2->finish;
$i++;
}
)
我的第二个评论是你的函数cosine_similarity
是对称的(即cosine_similarity(x,y) = cosine_similarity(y,x)
)。因此,如果您向ORDER BY uniqueid
添加$sql
并对$sql2
进行适当更改,只能获取uniqueid >= $uniqueId
的行,则可以减少近50%的时间。
答案 2 :(得分:0)
是否可以在语句句柄上使用'fetchrow_arrayref'而不是'fetchrow_hashref'?然后,您必须使用特定的数组索引而不是散列键来获取值。
while ($row = $sth->fetchrow_arrayref) {
my $flagSingleRow = 0;
$uniqueId = $row->[0];
$msg1 = $row->[1];
$sender = $row->[2];
$receiver = $row->[3];
$unixdate = $row->[4];
...
# and similarly for $sth2
数组中每个字段的实际位置取决于select语句中列的顺序。 试一试,让我们知道结果。
答案 3 :(得分:0)
似乎我的程序的主要问题是使用$ sfx-> hash_fv。我必须提出一些改进这一功能的想法。这不是我自己的功能,它来自SpeedyFx包。无论如何,谢谢你们。