【问题标题】:Is there a way that I can force mod_perl to re-use buffer memory?有没有办法强制 mod_perl 重新使用缓冲内存?
【发布时间】:2011-01-27 23:28:59
【问题描述】:

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

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

【问题讨论】:

  • 澄清一下,我自己没有使用任何缓冲区,我的代码也没有泄漏。考虑以下简单示例: sub handler { my $request = shift;我的 $boundary = 时间; $request->content_type("multipart/x-mixed-replace;boundary=\"$boundary\";"); for (;;) { $request->print("--$boundary\n"); $request->print("内容类型: text/html; charset=utf-8;\n\n"); $request->print("$data\n\n"); $request->rflush; } 返回 Apache2::Const::OK; } 这严重泄漏,我的请求保持活动状态,因此它可能会活跃数天。

标签: perl memory mod-perl2


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

      • 分配一个空字符串仍然保留 PV!只有 undef 函数可以删除它。但是,两者都不会杀死最后一个引用。正确的做法是让不需要的变量超出范围。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      • 1970-01-01
      • 2011-01-26
      • 2015-02-15
      • 2012-11-04
      相关资源
      最近更新 更多