在 Perl 中,我生成了一个巨大的只读数据结构,然后fork()
.
这是为了在分叉时利用 RSS 页面上的 COW。它工作得非常好,但是当一个子进程退出时,它会在死亡之前从 itelf 分配所有 RAM。
有没有办法避免这种无用的分配?
这是显示该问题的示例 Perl 代码。
#! /usr/bin/perl
my $a = [];
# Allocate 100 MiB
for my $i (1 .. 100000) {
push @$a, "x" x 1024;
}
# Fork 10 other process
for my $j (1 .. 10) {
last unless fork();
}
# Sleep for a while to be able to see the RSS
sleep(5);
在示例vmstat
输出中,我们可以看到它首先只分配了 100MiB,然后在第一次睡眠后它分配了一小段时间,然后全部释放。
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 1329660 80596 86936 0 0 21 18 160 25 0 0 100 0 0
1 0 0 1328048 80596 86936 0 0 0 0 1013 44 0 0 100 0 0
0 0 0 1223888 80596 86936 0 0 0 0 1028 76 11 5 84 0 0
0 0 0 1223888 80596 86936 0 0 0 0 1010 40 0 0 100 0 0
0 0 0 1223888 80596 86936 0 0 0 0 1026 54 0 0 100 0 0
0 0 0 1223888 80596 86936 0 0 0 0 1006 39 0 0 100 0 0
13 0 0 741156 80596 86936 0 0 0 0 1012 66 13 58 28 0 0
0 0 0 1329288 80596 86936 0 0 0 0 1032 60 0 0 100 0 0
注意:这似乎不是 Perl 版本特定的问题。当我测试 5.8.8、5.10.1 和 5.14.2 时,它们都表现出这种行为。
更新:
正如@choroba 在评论中所问的那样,我也尝试undef
了数据结构,但似乎它在分配 RAM 时触发了内存接触。
您可以在第一个脚本的末尾添加以下代码段。
# Unallocate $a
undef $a;
# Sleep for a while to be able to see the RSS
sleep(5);