免责声明我不确定我是否使用了正确的术语。它可能不是导致下面提到的膨胀的 optree:它可能是加载的符号DynaLoader
没有被释放。
是否可以使用一个模块,例如POSIX.pm
,卸载它并减少(缩小或修剪)optree,而无需任何一个
- 执行perl
- 分叉
我尝试过的事情,
这是一个简单的测试,创建一个文件 test.pl
$|++;
use Symbol;
use Class::Unload;
use POSIX;
print "GOT POSIX";
sleep(3);
no POSIX;
Class::Unload->unload('POSIX');
Symbol::delete_package('POSIX');
print "unloaded";
sleep(3);
外壳命令
perl ./test.pl & watch -n1 'ps -C perl -o "cmd rss";'
您可能会也可能不会看到 RSS 大小的增加(POSIX 可能会在watch
spawns之前加载ps
)。但是,我想看到它缩回去。
追踪POSIX.pm
我看到它使用XSLoader
的到底是什么DynaLoader
。
进行一些快速比较检查后,/proc/$$/smaps
我确定使用 POSIX.pm 会导致堆分配表示空间差异。使用 POSIX.pm 时,堆上的第一个分配要大得多:
56122fe4c000-561230040000 rw-p 00000000 00:00 0 [heap]
Size: 2000 kB
Rss: 1956 kB
Pss: 1956 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 1956 kB
Referenced: 1956 kB
Anonymous: 1956 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr mr mw me ac sd
对比
560c9f6ba000-560c9f6fc000 rw-p 00000000 00:00 0 [heap]
Size: 264 kB
Rss: 220 kB
Pss: 220 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 220 kB
Referenced: 220 kB
Anonymous: 220 kB
AnonHugePages: 0 kB
ShmemPmdMapped: 0 kB
Shared_Hugetlb: 0 kB
Private_Hugetlb: 0 kB
Swap: 0 kB
SwapPss: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Locked: 0 kB
VmFlags: rd wr mr mw me ac sd
我已经确认了一些事情,对命名空间进行核对不会将打开的文件句柄删除到POSIX.so
并且Fnctl.so
- 我用lsof
. 这本身就有些令人担忧。我认为在被调用者的包上分配句柄是有意义的。XSLoader
还掩盖了您可以释放该文件句柄 - DynaLoader
.
此外,似乎在libc
/dlfcn.h
我有
dlclose()
函数 dlclose() 减少句柄引用的动态加载的共享对象的引用计数。如果引用计数降至零,则对象被卸载。在句柄引用的对象上调用 dlopen() 时自动加载的所有共享对象都以相同的方式递归关闭。
从 dlclose() 成功返回并不能保证与句柄关联的符号已从调用者的地址空间中删除。除了由显式 dlopen() 调用产生的引用之外,由于其他共享对象中的依赖关系,共享对象可能已被隐式加载(并且引用计数)。只有当所有引用都被释放后,才能从地址空间中删除共享对象。
所以我猜这可能是可疑的,DynaLoader::dl_unload_file
正在调用dlclose
并且它似乎确实有效。
foreach my $dlref ( @DynaLoader::dl_librefs ) {
print DynaLoader::dl_unload_file($dlref);
}
在我对所有加载的文件进行核对DynaLoader
并XSLoader
通过执行上述操作后,RSS 仍然没有下降。