【问题标题】:Shared objects overhead共享对象开销
【发布时间】:2011-10-19 11:44:43
【问题描述】:

我们有一个非常模块化的应用程序,其中包含许多共享对象 (.so)。有人认为,在内存/闪存有限的低端平台上,最好将所有内容静态链接到一个大的可执行文件中,因为共享对象有开销。

您对此有何看法?

最好的问候,

保罗

【问题讨论】:

    标签: c linux embedded shared-libraries


    【解决方案1】:

    共享库的成本大致为(每个库):

    • 至少 4k 的私有脏内存。
    • 至少 12k 的虚拟地址空间。
    • 多个文件系统访问系统调用、mmapmprotect 系统调用,以及加载时至少一个页面错误。
    • 是时候解析库代码中的符号引用了。

    加上与位置无关的代码成本:

    • 丢失一个通用寄存器(这在 x86(32 位)上可能很大,但在其他架构上几乎无关紧要)。
    • 额外的间接访问全局/静态变量(和常量)。

    如果您有一个大型的长期运行的应用程序,那么成本对您来说可能根本不重要,除非您使用的是小型嵌入式系统。另一方面,如果您正在编写一些可能会为短期任务(如语言解释器)多次调用的东西,那么这些成本可能是巨大的。将所有标准模块放在它们自己的 .so 文件中而不是默认静态链接它们是 Perl、Python 等启动如此缓慢的重要原因。

    就个人而言,我会采用将动态加载模块用作可扩展性工具而不是开发模型的策略。

    【讨论】:

    • 谢谢!您能否请一些参考资料或背景资料,以使 4k 或 12k 之类的数字在此答案中看起来不神奇?
    • @user894319twitter:4k 是大多数拱门上的页面大小,包括 x86 和 arm。您必须有至少一页包含 GOT 等的可写数据(不与 fs 缓存共享,因为它已被修改)等。至少这一页和可共享代码(文本)段构成两页虚拟地址空间,还有第三个我忘记了。
    【解决方案2】:

    除非内存非常紧张,否则这些文件的一份副本的大小不是主要的决定因素。鉴于这是一个嵌入式系统,您可能很清楚哪些应用程序将使用您的库以及何时使用。如果您的应用程序打开和关闭它尽职尽责地引用的多个库,并且您永远不会同时打开所有库,那么共享库将显着节省 RAM。

    您需要考虑的另一个因素是性能损失。打开共享库需要一小段时间(通常是微不足道的);如果您有一个非常慢的处理器或难以满足实时要求,则静态库不会导致共享库的加载损失。分析以确定这是否重要。

    综上所述,在某些特殊情况下,共享库可以明显优于静态库。在大多数情况下,它们几乎没有伤害。在简单的情况下,您不会从共享库中获益。


    当然,如果您有多个使用同一个库的应用程序(或应用程序的版本),共享库将在 Flash 中节省大量资金。如果您使用静态库,则会将一个副本(与共享库 [1] 的大小大致相同)编译到每个库中。当您在 PC 工作站上时,这很有用。但你知道的。您正在使用一个仅由一个应用程序使用的库。


    [1] 各个库文件的内存差异很小。共享库添加索引和符号表,以便dlopen(3) 可以加载库。这是否重要取决于您的用例;为每个编译,然后比较大小以确定 Flash 中哪个更小。您必须运行并分析以确定哪个消耗更多 RAM;除了共享库的初始加载之外,它们应该是相似的。

    【讨论】:

      【解决方案3】:

      拥有大量库当然意味着必须存储更多元数据,并且在加载时需要将其中一些元数据(库节标题等)存储在 RAM 中。但即使在(中等现代的)嵌入式系统上,差异也应该可以忽略不计。

      我建议你尝试这两种方案,并测量 FLASH 和 RAM 中的已用空间,然后决定哪个最好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-30
        • 2011-12-23
        • 2017-04-22
        • 1970-01-01
        • 2013-04-21
        • 2011-02-06
        • 2013-05-05
        • 1970-01-01
        相关资源
        最近更新 更多