办公室的其他人正在讨论如何通过将内部库的非必要部分切割成单独的库来减少内存占用和加载时间,并按需加载它们。
我今晚做了一些谷歌搜索,了解到ld.so
加载了具有延迟绑定的库,ld.so
和dlopen
都加载了mmap
的库。这似乎意味着库中那些非必要部分已按需加载,即只要未使用函数/库中的数据页未被读取,
没有空间和
加载和分配这些页面不需要时间。
所以我认为他们只需要确保他们不会主动接触所有非必要组件。
这是真的?这对所有posix
系统都是真的(实际上)吗?
答案 0 :(得分:0)
任何直接链接到您的程序或直接依赖项的库仍会在运行时进行映射和加载。要查看将打开哪些库,您可以使用ldd some_program
。其中一些将是也将加载的间接依赖项。要仅查看直接相关性,可以使用objdump -x my_program | grep NEEDED
。不仅必须从磁盘读取每个库(可能相对较慢),而且必须映射来自它们的所有必要符号(有时很多)。
可能是在启动时不一定需要的依赖项可能会占用整个库大小的大部分。如果您可以将不同的功能拆分为可以作为模块加载的功能单元,则可以直接减少启动时间,并在一定程度上减少内存占用。
我能想到的最简单的例子是图像查看器应用程序,其中GUI库链接到二进制文件,但实际的图像加载是由模块完成的。 (feh将是使用Imlib2或可选的gdk-pixbuf进行图像加载的示例。这允许主GUI启动而无需加载libpng,libjpeg,libXPM,libcairo,librsvg等...这减少了启动时间,因为这些都不需要加载,并且可能永远不会被加载,从而减少了内存占用
在C中,通常使用dlopen()
,dlsym()
和dlclose()
(使用平面二进制格式的嵌入式系统可以使用特殊链接的模块),但大多数工具包都有自己的模块实现(例如Gtk +使用glib的跨平台模块加载)。
不必切割和干燥。你可以很容易地将你的初始GUI分成几个部分,并依次dlopen()它们作为一个单独的"闪屏"的替代方案。我不知道任何允许这样做的工具包的例子,但是人们甚至可以打开带有标题和维度的X11窗口,然后将GUI和相关的库加载到该窗口中。您可以根据文件的扩展名/魔术值加载不同的二进制格式解析器,或者根据用户决定使用Save_As的格式加载不同的二进制格式生成器。
另一种方法是静态链接库依赖项,以便只加载所需的符号(只要这样做没有许可问题)。当你只使用10个时,为什么要加载100多个小部件?这对于使用静态链接构建的库(例如musl-libc)非常有效(glibc对于静态链接而言是众所周知的无用的)。使用-flto编译器标志(或旧版本的gcc上的-combine -fwhole-program)以及-ffunction-sections和-fdata-sections进行编译并使用--gc-sections进行链接通常会有所帮助(我通常会看到15-50%)如果您不能依赖共享系统库来保持理智,那么这也是一个不错的选择。