免责声明我不确定我使用的术语是否正确。可能不是由optree引起下面所述的膨胀:可能是DynaLoader加载的符号未释放。

是否可以使用模块,例如POSIX.pm,将其卸载并减少(缩小或修剪)optree,而无需

  • 重新执行perl
  • fork

  • 我尝试过的事情
  • Class::Unload->unload('POSIX');
  • Symbol::delete_package('POSIX');
  • 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);
    

    Shell命令
    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
    

    我已经确认了几件事,对 namespace 进行操作并不会将打开的文件句柄放到POSIX.soFnctl.so中-我是通过lsof确定的。这本身有点令人担忧。我认为在被调用者的程序包上分配句柄是有意义的。 XSLoader也使您无法释放该文件句柄-DynaLoader中提供了一项功能。

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



    因此,我猜测这可能是令人怀疑的,DynaLoader::dl_unload_file正在调用 dlclose ,它似乎确实有效。
    foreach my $dlref ( @DynaLoader::dl_librefs ) {
      print DynaLoader::dl_unload_file($dlref);
    }
    

    在通过上述操作对所有加载了DynaLoaderXSLoader的文件进行核对之后,RSS仍然没有删除。

    最佳答案

    一般来说,没有。棘手的细节是几乎没有人缩减自己的内存,因为几乎每个人都使用C库malloc(和 friend )调用来直接或间接地分配内存。而且,没有(标准的)方法可以告诉C库释放内存(将其发送回OS)。 Perl在这里没有什么不同-一旦malloc ed和free d,Perl依赖的C库保留内存以备将来使用,因此,如果您需要重用内存,则不需要昂贵的内核调用(特别是brk),可以简单地重用。实际上,这就是您的卸载方案正在做的事情-当您返回并在其余服务器进程中重复使用下一个2MB内存时,您将重新使用内存,而不是调用brk,那么您就可以快点。

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

    其他选择是要么硬着头皮,在 fork 任何服务器之前加载POSIX(这应该将所有内容保留在共享的写时复制内存中,因此对于5k服务器仅占用2MB的内存),或者 fork 加载在 child 中使用POSIX,进行肮脏的工作,退出 child ,然后继续在 parent 中工作。对我来说,这似乎相对较慢。

    09-10 03:27
    查看更多