【问题标题】:How does library size affects an application's load time and memory foot print?库大小如何影响应用程序的加载时间和内存占用?
【发布时间】:2015-01-09 06:51:38
【问题描述】:

办公室里的其他一些人正在讨论通过将内部库的非必要部分切割成单独的库并按需加载来减少内存占用和加载时间。

今晚我在谷歌上搜索了一下,得知ld.so 使用延迟绑定加载库,ld.sodlopen 都使用mmap 加载库。这似乎意味着库的那些非必要部分已经按需加载,即只要不使用函数/不读取库中的数据页,

  1. 不占用空间

  2. 加载和分配这些页面不需要时间。

所以我认为他们只需要确保他们不会主动接触所有非必要的组件。 这是真的?这对所有posix 系统都是真的(实际上)吗?

【问题讨论】:

  • 您要解决的真正问题是什么?这个应用程序适用于小型系统吗?如果没有,您可以购买更多内存吗?您现在使用了多少内存,您的最终目标是什么?
  • “内存占用”是指驻留集大小吗?还是虚拟内存使用?还是什么?
  • 这是一个嵌入式系统。我完全同意你的看法,如果我们谈论的是 PC,这个问题完全无关紧要。
  • @DavidSchwartz,我关心虚拟内存的使用,虽然更重要的是加载时间。
  • 您有多少可用内存?现在用了多少?您的目标用途是什么?

标签: linux memory embedded posix dlopen


【解决方案1】:

任何直接链接到您的程序或直接依赖的库仍会在运行时映射和加载。要查看将打开哪些库,您可以使用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 的格式加载不同的二进制格式生成器。

另一种选择是静态链接库依赖项,以便仅加载所需的符号(只要这样做没有许可问题)。为什么要加载 100 多个小部件,而您只使用 10 个?这最适用于使用静态链接构建的库,例如 musl-libc(众所周知,glibc 对静态链接毫无用处)。使用 -flto 编译器标志(或旧版本 gcc 上的 -combine -fwhole-program)以及 -ffunction-sections 和 -fdata-sections 并与 --gc-sections 链接通常会有所帮助(我通常看到 15-50%减少大小)如果您不能依赖共享系统库来保持理智,这也是一个不错的选择。

【讨论】:

    猜你喜欢
    • 2014-11-24
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    • 2019-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多