gpt4 book ai didi

perl - 我可以使用一个模块,然后卸载它以缩小 Optree 吗?

转载 作者:行者123 更新时间:2023-12-01 19:24:04 26 4
gpt4 key购买 nike

免责声明 我不确定我使用的术语是否正确。它可能不是 Optree 造成下面提到的膨胀:它可能是 DynaLoader 加载的符号。没有被释放。

是否可以使用模块,例如 POSIX.pm ,卸载它并减少(收缩或修剪)optree,而不需要任何一个

  1. 重新执行 perl
  2. fork

我尝试过的事情

  1. Class::Unload->unload('POSIX');
  2. Symbol::delete_package('POSIX');
  3. no POSIX;

这是一个简单的测试,创建一个文件 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 生成 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.soFnctl.so -- 我用 lsof 确定了这一点。这本身就有些令人担忧。我认为在被调用者的包上分配句柄是有意义的。 XSLoader还掩盖了您可以释放该文件句柄——DynaLoader中提供的功能。 。

此外,似乎在libc中/dlfcn.h我有

dlclose()

The function dlclose() decrements the reference count on the dynamically loaded shared object referred to by handle. If the reference count drops to zero, then the object is unloaded. All shared objects that were automatically loaded when dlopen() was invoked on the object referred to by handle are recursively closed in the same manner.

A successful return from dlclose() does not guarantee that the symbols associated with handle are removed from the caller's address space. In addition to references resulting from explicit dlopen() calls, a shared object may have been implicitly loaded (and reference counted) because of dependencies in other shared objects. Only when all references have been released can the shared object be removed from the address space.

所以我猜这可能是可疑的,DynaLoader::dl_unload_file正在调用 dlclose 它似乎确实有效。

foreach my $dlref ( @DynaLoader::dl_librefs ) {
print DynaLoader::dl_unload_file($dlref);
}

在我删除了所有加载 DynaLoader 的文件之后和XSLoader通过执行上述操作,RSS 仍然没有下降。

最佳答案

一般来说,没有。关键的细节是,几乎没有人收缩自己的内存,因为几乎每个人都直接或间接地使用 C 库 malloc (和 friend )调用来分配内存。并且没有(标准)方法告诉 C 库释放内存(将其发送回操作系统)。 Perl 在这里没有什么不同 - 一旦进行了 malloc 和 free 处理,Perl 所依赖的 C 库就会保留内存以供将来使用,这样如果您需要重用这些内存,不需要昂贵的内核调用(具体来说,brk),并且可以简单地重用。事实上,这就是您的卸载场景所做的 - 当您返回并在服务器进程的其余部分中重用下一个 2MB 时,您将重新使用内存,而不是调用 brk,你会更快。

如果您自己接管内存分配所有权并调用 brk ,这是可能的,但这很少值得。让 perl 使用该分配器需要对 perl 进行一些代码更改并重新编译。可能不是您想要做的。

其他选择是要么咬紧牙关,在 fork 任何服务器之前加载 POSIX(这应该将所有内容保留在共享的写时复制内存中,因此对于 5k 服务器仅占用 2MB 内存),或者fork,在子进程中加载​​ POSIX,完成脏工作,退出子进程,然后在父进程中继续。这对我来说似乎相对较慢。

关于perl - 我可以使用一个模块,然后卸载它以缩小 Optree 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46738256/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com