Disclaimer I'm not sure I'm using the right terms. It may not be the optree responsible for the bloat mentioned below: it may be the symbols loaded by DynaLoader that are not freed.

Is it possible to use a module, like POSIX.pm , unload it and lessen (shrink, or prune) the optree without either

Rexecing perl Forking

Things I've tried,

Here is an easy test create a file 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 command

perl ./test.pl & watch -n1 'ps -C perl -o "cmd rss";'

You may or may not be able to see the RSS size increase (POSIX may load before watch spawns ps ). But, I want to see it shrink back down.

Tracking down what exactly POSIX.pm does I see it uses XSLoader which uses DynaLoader .

Doing some quick comparative checks in /proc/$$/smaps I've determined that using POSIX.pm causes a heap allocation that represents the difference in space. The first allocation on the heap, is massively bigger when using 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

vs

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

I've confirmed a few things, nuking the namespace does not drop the open file handle to POSIX.so and Fnctl.so -- I determined this with lsof . That is in itself somewhat concerning. I would think it would make sense to allocate the handle on the callee's package. XSLoader also obscures that you can release that file handle -- a feature available in DynaLoader .

Further, it seems that in libc / dlfcn.h I have

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.

So I'm guessing that may be suspect, DynaLoader::dl_unload_file is calling dlclose and it does seems to work.

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