我继承了一个在 EC2 实例上运行的 Perl 脚本,该脚本基本上会抓取一堆 URL 以获取数据(也称为抓取)。调用此脚本的方式是通过一个 shell 脚本,该脚本会分叉多个这些 perl 脚本。根据抓取进度,任何给定点都可能有数百个这样的 Perl 脚本在运行。
每个 Perl 脚本都会这样做:
## create a temporary hash to hold everything ##
my %products = ();
并且正如您所想象的,随着更多产品在该过程中被刮取,该阵列将会不断增大。
我的问题是:当 perl 尝试将下一个产品添加到“产品”数组中,但没有可用内存时会发生什么?它只是等待还是会死掉?我的直觉告诉我它会死掉,但我如何使用 malloc 样式的内存分配,如果它无法分配内存,它就会等待?
仅限制子进程的数量是否更好?
任何想法都将不胜感激。
ps 这是 perl,v5.10.1 (*) 为 i486-linux-gnu-thread-multi 构建
答案1
不确定 Perl 的具体情况,但在其他动态语言(如 Python)中,您会遇到内存分配失败,随后程序崩溃。有些语言(包括 Python)允许您为这种情况安装处理程序,Perl 可能也会这样做。
我不确定您从哪里得到这样的想法,即 malloc 在无法分配内存时会等待,如果请求失败,Linux 上的实现会返回一个指针或 NULL。
Linux 上的情况更加复杂,因为 Linux 默认允许内存过度分配。例如,如果您的系统有 4 GB 的虚拟内存可用,您可以让多个进程分配近 4GB 的内存。直到它们弄脏分配,内存才会真正被使用。如果多个进程最终这样做,它们将耗尽实际可用内存,并且内存不足终止进程将启动并终止一些进程。
对您来说,简单的解决方案就是观察进程使用了多少内存,并且一次只允许一定数量的进程运行。更复杂的解决方案包括使用固定长度的数据结构,以便了解内存使用情况,或者将结果直接或通过缓冲区流式传输到磁盘,以保持较低的使用率。解决方案实际上取决于应用程序,如果没有其功能的详细信息,很难提出更具体的建议。