我创建了一个简单的perl脚本来读取日志文件并异步处理数据。
我面临的问题是脚本在运行的时间越长,就会持续使用更多内存。这似乎受其处理的数据量的影响。我遇到的问题是我无法确定究竟是什么使用了所有这些内存,以及它是否是泄漏或其他东西只是坚持它。
如何修改以下脚本以使其不再持续消耗内存?
#Multithreaded to read multiple log files at the same time.
use strict;
use warnings;
use threads;
use Thread::Queue;
use threads::shared;
my $logq = Thread::Queue->new();
my %Servers :shared;
my %servername :shared;
sub csvsplit {
my $line = shift;
my $sep = (shift or ',');
return () unless $line;
my @cells;
my $re = qr/(?:^|$sep)(?:"([^"]*)"|([^$sep]*))/;
while($line =~ /$re/g) {
my $value = defined $1 ? $1 : $2;
push @cells, (defined $value ? $value : '');
}
return @cells;
}
sub process_data
{
while(sleep(1)){
if ($logq->pending())
{
my %sites;
my %returns;
while($logq->pending() > 0){
my $data = $logq->dequeue();
my @fields = csvsplit($data);
$returns{$fields[$#fields - 1]}++;
$sites{$fields[$#fields]}++;
}
print "counter:$_, value=\"$sites{$_}\" />\n" for (keys%sites);
print "counter:$_, value=\"$returns{$_}\" />\n" for (keys%returns);
}
}
}
sub read_file
{
my $myFile=$_[0];
open(my $logfile,'<',$myFile) || die "error";
my $Inode=(stat($logfile))[1];
my $fileSize=(stat($logfile))[7];
seek $logfile, 0, 2;
for (;;) {
while (<$logfile>) {
chomp( $_ );
$logq->enqueue( $_ );
}
sleep 5;
if($Inode != (stat($myFile))[1] || (stat($myFile))[7] < $fileSize){
close($logfile);
while (! -e $myFile){
sleep 2;
}
open($logfile,'<',$myFile) || die "error";
$Inode=(stat($logfile))[1];
$fileSize=(stat($logfile))[7];
}
seek $logfile, 0, 1;
}
}
my $thr1 = threads->create(\&read_file,"log");
my $thr4 = threads->create(\&process_data);
$thr1->join();
$thr4->join();
当程序有数据要处理时,内存似乎只会增加,如果我离开它,它会维持当前的内存使用量。
对于更大的吞吐量,内存似乎只会增加,并且同时在大约2000行中每5秒增加大约半个Mb。
我没有包含csv,因为我认为它不相关。如果您这样做并希望我添加它,请提供正确的理由。
GNU bash, version 3.2.57(1)-release (s390x-ibm-linux-gnu)
perl, v5.10.0
我已经查看过其他问题,但找不到太多相关性。如果这是重复或相关信息在另一个问题中,请随意标记为欺骗并生病检查。
需要更多信息才能询问。
答案 0 :(得分:2)
原因可能是Thread::Queue
的大小无限制。如果生产者线程比消费者线程更快,那么您的队列将继续增长。所以你应该只是limit the size of your queue。例如,要设置1,000个队列项的限制:
$logq->limit = 1000;
(顺便使用pending
方法的方法是错误的。只有在返回值未定义的情况下才应该终止。)