有没有办法可以强制mod_perl重用缓冲区内存?

时间:2010-03-16 05:15:17

标签: perl memory mod-perl2

我有一个在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; 
  } 

这种情况严重泄漏,我的请求仍然存在,因此可能会持续数天。

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:0)

你的for(;;)循环永远不会像写入那样结束,这会导致比泄漏内存更糟的问题。 print方法必须分配一些内存,可能作为请求记录的一部分,通常在清理请求时释放。这发生在C代码中,在mod_perl2或Apache2中。

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

答案 2 :(得分:-1)

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

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

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