2

我有一个在 mod_perl 中运行的 Perl 脚本,它需要向客户端写入大量数据,可能需要很长时间。我观察到的行为是,一旦我打印并刷新某些内容,即使我也不会回收缓冲内存rflush(我知道操作系统无法回收它)。

这就是 mod_perl 的操作方式吗?有没有一种方法可以强制它定期释放缓冲内存,以便我可以将其用于新的缓冲区,而不是从操作系统中获取更多?

澄清一下,我自己没有使用任何缓冲区,我的代码也没有泄漏。考虑以下简单示例:

  sub handler { 
     my $request = shift; 
     my $boundary = time; 
     $request->content_type("multipart/x-mixed-replace;boundary=\"$boundary\";"); 
     for (;;) { 
        $request->print("--$boundary\n"); 
        $request->print("Content-type: text/html; charset=utf-8;\n\n"); 
        $request->print("$data\n\n"); 
        $request->rflush;
     } 
     return Apache2::Const::OK; 
  } 

这严重泄漏,并且我的请求保持有效,因此它可能会活跃数天。

4

3 回答 3

2

不将内存返回给操作系统是perl解释器本身的标准行为,并不特定于 mod_perl 本身。除了使用共享内存(IIRC,您手动处理分配/取消分配)或终止进程之外,我不知道有任何方法可以perl将内存释放回主机操作系统。

让变量超出范围将允许perl将该内存重新用于其他变量,但不会将其返回给操作系统。

编辑: 我只是重新阅读了这个问题,并意识到您只是在寻找一种让perl重新使用内存的方法,而不是试图将其释放到操作系统。在这种情况下,使用词法 ( my) 变量并将它们限制在尽可能小的范围内,而不是尽早定义全局缓冲区并永远保留它应该可以解决问题。

于 2010-03-16T11:43:49.353 回答
0

您的 for(;;) 循环永远不会按原样结束,这将导致比内存泄漏更严重的问题。print 方法必须分配一些内存,可能作为请求记录的一部分,通常在清理请求时释放。这发生在 C 代码中,无论是在 mod_perl2 还是 Apache2 中。

你必须重新设计你的方法来解决这个问题。不要从 mod_perl 处理程序中发送长时间运行的响应,而是通过 ProxyPass 设置将用户重定向到将响应打印到 STDOUT 的程序。(本质上是一个 CGI 脚本。)该脚本可以是纯 perl,其他发布者提到的有关限制变量范围的技术将起作用。响应仍将通过 Apache,但是当作为反向代理运行时,Apache 有一组固定的缓冲区,它在存储桶中复制数据;尽管传递了大量数据,但我从未见过我的反向代理进程消耗大量内存。

于 2010-06-02T02:00:35.213 回答
-1

释放对缓冲区的所有引用。例如,如果您使用字符串作为缓冲区,如

$buf = "really long string " . "and other methods that make it huger";
print SOMEWHERE $buf;
$buf = ""; # or undef $buf according to taste

应该将以前由 $buf 指向的存储返回到空闲池。

于 2010-03-16T05:23:33.600 回答