【问题标题】:Perl memory leak in threads (threads don't release memory)线程中的 Perl 内存泄漏(线程不释放内存)
【发布时间】:2012-10-11 00:04:01
【问题描述】:

我现在正在搜索 2 周关于此问题的信息,但我似乎无法在网上搜索找到任何答案。

所以,这里有两段代码:

1:

#! /usr/bin/perl

#
# RELEASE MEMORY
#

use threads;

my @child;

$ii=0;


while (1)
{
  my @child = threads->new(\&test, "test");
  $_->detach for @child;
  print "$ii\n";
  $ii++;
}

sub test {
    my ($ee) = 0;    
}

2:

#! /usr/bin/perl

#
# DO NOT RELEASE MEMORY
#

use threads;

my @child;

$ii=0;


for($ii=0;$ii<2000;$ii++) {
    my @child = threads->new(\&test, "test");
    $_->detach for @child;
    print "$ii\n";
}

while(1)
{
  sleep(10);
}

sub test {
    my ($ee) = 0;    
}

所以这就是问题所在。第一个代码只运行一个无限循环,大约每 2 秒将内存释放回操作系统(根据 ps)

第二个代码也在释放内存,但仅当他在“for”循环中运行时。 一旦它退出 for 循环并进入无限循环,所有尚未释放到 for 循环中的内存永远不会释放回操作系统。

有人遇到同样的问题吗?

Perl: (v5.16.1) 为 x86_64-linux-thread-multi 构建

操作系统:Debian 6.0.5

非常感谢


编辑 1: 我使用了 800 个线程,并且都通过打印 $ee var 验证了它们是否退出。

但是一旦进入 while(1) 循环,这里就是 ps aux | grep perl 输出:

root@srv:~# ps aux | grep perl
root      6807 41.5  2.5 387780 209580 pts/0   S+   16:38   0:02 /opt/ActivePerl-5.16/bin/perl /home/tttlast.pl
root      7627  0.0  0.0   7548   856 pts/1    S+   16:38   0:00 grep perl

所以所有线程都退出了,但内存使用量仍然是我服务器总内存的 2.5%。 因此,除非我终止程序,否则内存仍在使用中。


编辑 2:

我解决了我的问题,我改变了我的结构。事实上,主程序(长期运行的)已经被分离出来,我使用小程序等待所有线程完成退出。

这种方式不会填满虚拟内存,其他守护进程也不会被杀死。

感谢所有引导我找到解决方案的人。

【问题讨论】:

  • 我已经在 OS X 10.8 / Perl 5.16.0 上试过了。我首先看到的行为是在大约 6 megs 驻留的几千个线程之后内存使用水平下降。第二个水平大致相同,并在睡眠时保持在那里。在这两种情况下,线程内存显然都被释放了。您能否发布更多证据表明内存没有被释放?也许ps 每秒输出一次?
  • 添加了 ps 输出。其实真正的程序更复杂,只是为了不被喷,才没有贴在这里,但是它运行了很长时间,每个小时打开大约 250 到 900 个线程,将内存填满到我总内存的 10% 左右,并且永远不会释放.但这与第二个示例完全相同。如果您需要更多信息,请告诉我。谢谢
  • 如果我错了,请纠正我,但是当一个 进程 退出时,Perl only 不释放内存吗?这是一个长期存在的“功能”,我在最近的 perldelta 中找不到任何关于线程优化的证据。您声称目睹的内存使用量减少比“泄漏”更让我感到惊讶。
  • If Perl is using the system's malloc, Perl may release memory back to the operating system。检查perl -wle 'use Config; print $Config{usemymalloc}'。另外,ps is not a wholly reliable way of checking memory usage on Linux,你可以试试 pmap。最后,不知道ps是怎么处理线程的。
  • 刚刚使用 pmap 检查了第一个和第二个脚本,结果相同(第一个释放内存,第二个不释放内存)。在这个例子中,我可以检查线程是否正在运行,当没有人在运行时,我会杀死并重新启动应用程序,但使用我的真实程序我无法做到这一点。我还检查了 perl -wle 'use Config; print $Config{usemymalloc}' 并且它可能表示“n”为否。所以如果我没有编译 perl 来使用 malloc 为什么它会从脚本一而不是从脚本二释放内存?

标签: multithreading perl memory-leaks


【解决方案1】:

这里没有“问题”。这都是正常的预期行为。如果这给您带来了某种问题,那么您还没有解释它是什么。

没有理由将虚拟内存归还给操作系统,因为虚拟内存不是稀缺资源。没有理由将物理内存归还给操作系统,因为无论如何,如果它有更好的用途,操作系统就会占用它。

没有证据表明这是内存泄漏。测试结果表明,内存使用量不会无限制地增加——在所有情况下,它最终都会趋于平稳。

【讨论】:

  • 刚刚验证,您是对的。当 perl 程序需要内存时,会占用其他进程使用的内存。事实上,问题在于 perl 占用内存的其他进程被杀死,如 mysql 和邮件服务器。并且perl程序使用mysql和邮件服务器来运行。我应该编辑我的帖子还是发布另一个问题?顺便说一句,非常感谢
  • 你只是不应该创建这么多线程。这是不明智的。
猜你喜欢
  • 2021-02-25
  • 2014-10-29
  • 2013-12-18
  • 2017-02-04
  • 2016-12-09
  • 2020-08-08
  • 2012-02-17
  • 2016-01-26
  • 1970-01-01
相关资源
最近更新 更多