简体   繁体   English

有没有一种方法可以强制mod_perl重新使用缓冲存储器?

[英]Is there a way that I can force mod_perl to re-use buffer memory?

I have a Perl script running in mod_perl that needs to write a large amount of data to the client, possibly over a long period. 我有一个在mod_perl中运行的Perl脚本,该脚本可能需要很长时间才能向客户端写入大量数据。 The behavior that I observe is that once I print and flush something, the buffer memory is not reclaimed even though I rflush (I know this can't be reclaimed back by the OS). 我观察到的行为是,一旦我打印并刷新了某些内容,即使我进行了rflush ,缓冲存储器也不会被回收(我知道操作系统无法回收该内存)。

Is that how mod_perl operates and is there a way that I can force it to periodically free the buffer memory, so that I can use that for new buffers instead of taking more from the OS? 那是mod_perl的工作方式,有没有办法让我强制它定期释放缓冲区内存,以便可以将其用于新缓冲区,而不是从OS中获取更多内存?

Just to clarify, I'm not using any buffers myself and there are no leaks in my code. 为了澄清,我自己没有使用任何缓冲区,并且我的代码中没有泄漏。 Consider the following simple example: 考虑以下简单示例:

  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; 
  } 

This leaks heavily, and my request is being kept alive, so it may be active for days. 这严重泄漏,并且我的请求一直处于活动状态,因此它可能处于活动状态数天。

Not returning memory to the OS is the standard behavior of the perl interpreter itself, not specific to mod_perl per se. 不将内存返还给OS是perl解释器本身的标准行为,而不是特定于mod_perl本身。 Other than using shared memory (which, IIRC, you handle the allocation/de-allocation for manually) or terminating the process, I'm not aware of any way of getting perl to release memory back to the host OS. 除了使用共享内存(IIRC,您可以手动处理分配/取消分配)或终止进程外,我不知道有什么方法可以让perl将内存释放回主机OS。

Letting variables pass out of scope will allow perl to re-use that memory for other variables, but will not return it to the OS. 让变量超出范围将允许perl将内存重新用于其他变量,但不会将其返回给OS。

Edit: I just re-read the question and realized that you're just looking for a way to let perl re-use the memory, not attempting to release it to the OS. 编辑:我只是重新阅读了这个问题,并意识到您只是在寻找一种让perl重用内存的方法,而不是尝试将其释放到操作系统。 In that case, using lexical ( my ) variables and confining them to the smallest possible scope instead of defining a global buffer early and keeping it around forever should do the trick. 在那种情况下,使用词汇( my )变量并将其限制在尽可能小的范围内,而不是尽早定义全局缓冲区并将其永久保留就可以了。

Your for(;;) loop can never end as-written, which will lead to worse problems than leaking memory. 您的for(;;)循环永远都不能如原样结束,这将导致比泄漏内存更严重的问题。 The print method must allocate some memory, probably as part of the request record, which is normally released when the request is cleaned up. 打印方法必须分配一些内存(可能是请求记录的一部分),通常在清理请求时会释放这些内存。 This is happening in the C code, either within mod_perl2 or Apache2. 这发生在mod_perl2或Apache2中的C代码中。

You'll have to redesign your approach to get around this. 您必须重新设计您的方法来解决此问题。 Instead of sending the long-running response from within the mod_perl handler, redirect the user through a ProxyPass setting to a program that will print the response to STDOUT. 无需从mod_perl处理程序中发送长时间运行的响应,而是通过ProxyPass设置将用户重定向到将响应打印到STDOUT的程序。 (Essentially a CGI script.) The script can be pure-perl where the techniques other posters have mentioned about restricting scope of variables will work. (本质上是CGI脚本。)该脚本可以是纯Perl,在其他脚本中提到的限制变量范围的技术也可以使用。 The response will still pass through Apache, but when operating as a reverse proxy Apache has a fixed set of buffers that it copies the data through in a bucket-brigade; 响应仍将通过Apache,但作为反向代理运行时,Apache具有一组固定的缓冲区,可将其复制到存储桶中以通过数据; I've never seen my reverse proxy processes consume much memory despite passing through huge amounts of data. 尽管传递大量数据,但我从未见过我的反向代理进程会消耗大量内存。

Release any references you have to the buffer. 释放对缓冲区的任何引用。 For example, if you were using a string as a buffer as in 例如,如果您使用字符串作为缓冲区,如

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

Should return the storage formerly pointed to by $buf to the free pool. 应该将$ buf先前指向的存储返回到空闲池。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM