我编写了一个永远作为守护进程运行的Perl脚本。
my $CHILD_THREADS_CNT=5;
my $q= new Thread::Queue();
sub processJob{
while (defined(my $taskHandle = $q->dequeue()) ) {
my $obj=jobProcesser->new();
my $result=$obj->getOutput(taskHandle);
#jobProcessor is the large modules that computes/manipulates the job
//MySql Query to insert '$result' into DB
}
}
#Daemon subroutine
sub daemon{
while (1){
my @new_request= #'My SQL Queries that returns all new requests from db'
for (@new_request){
$q->enqueue($_);
}
sleep 5;
}
}
#Main thread scans the db, and, enqueue the new job in a queue.
my $scanDB=threads->create(\&daemon);
#children perform processing
my @child=map threads->create(\&processJob), 1..CHILD_THREADS_CNT;
$scanDB->join;
$q->enqueue(undef) for 1..CHILD_THREADS_CNT;
for (@child){
$_->join;
}
我使用nohup在unix(Perl v5.8.8)中运行此脚本。 脚本在每4-5天后死亡。没有hup没有捕获解释脚本突然死亡原因的日志(主要过程)。我预料到内存泄漏,并使用 top -p PID 来分析nohup进程。
随着脚本连续不断地运行, VIRT (虚拟内存)和 RES 内存大小不断增长。仅在10个小时内到达2GB左右。
基本上,一旦子线程完成作业(process-Job),即。 returns $result
,那么内存应该已经发布到操作系统。
我的线程实现内存是否有效?
需要进行哪些更改和优化才能永久运行脚本,不会中断或无需定期重启?
感谢任何帮助。
答案 0 :(得分:0)
正如评论中所提到的 - 这里没有明显的泄漏。
通过从队列中运行“worker”线程,你已经避免了一些关于线程编程的关键'陷阱'。
我建议你需要查看数据库调用和processJob
子目录中创建对象的情况。 OO中的常见陷阱是在对象内创建循环引用,因此即使对象超出范围,引用计数也不会降至零。
可能值得检查是否调用了析构函数。 (http://perldoc.perl.org/perlobj.html#Destructors)
DESTROY {
my ( $self ) = @_;
warn $self . " object destroyed";
}