共享对象开销

8
我们有一个非常模块化的应用程序,有许多共享对象(.so文件)。一些人认为,在内存/闪存有限的低端平台上,最好将所有内容静态链接到一个大可执行文件中,因为共享对象会增加开销。
您对此有何看法?
此致
敬礼,
Paul
3个回答

12
共享库的成本大致如下(每个库):
  • 至少4k的私有脏内存。
  • 至少12k的虚拟地址空间。
  • 几个文件系统访问系统调用,mmapmprotect系统调用以及加载时至少一个页面错误。
  • 用于解决库代码中符号引用的时间。

加上具有位置独立代码成本:

  • 丢失一般用途寄存器(在x86(32位)上可能非常巨大,但在其他体系结构上基本无关紧要)。
  • 额外的间接层次访问全局/静态变量(和常量)。

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

就我个人而言,我会选择使用动态加载的模块作为可扩展性工具,而不是作为开发模型


谢谢!您能否提供一些参考或背景信息,以便像4k或12k这样的数字在回答中不会看起来神奇? - user894319twitter
1
@user894319twitter:在大多数架构中,包括x86和arm,4k是页面大小。您必须至少有一页可写数据(不与fs缓存共享,因为它已被修改),其中包含GOT等内容。至少那一页和可共享的代码(文本)段占用了两个虚拟地址空间页面,还有一个我忘记的第三个页面。 - R.. GitHub STOP HELPING ICE

6
除非内存非常紧张,否则一个文件的副本大小不是主要决定因素。考虑到这是一个嵌入式系统,您可能已经很清楚哪些应用程序将使用您的库以及何时使用。如果您的应用程序忠实地打开和关闭多个库引用,并且您从未同时打开所有库,则共享库将大大节省RAM。
您需要考虑的另一个因素是性能惩罚。打开共享库需要一小段时间(通常微不足道);如果您有一个非常慢的处理器或难以满足实时要求,则静态库不会产生共享库的加载惩罚。进行分析以确定这是否重要。
总之,在某些特殊情况下,共享库可以比静态库显着更好。在大多数情况下,它们对性能几乎没有影响。在简单的情况下,您无法从共享库中获得任何好处。
当然,如果您有多个应用程序(或应用程序的版本)使用相同的库,则共享库将大大节省Flash。如果使用静态库,则每个库将编译为一个副本(与共享库大小相同)。当您在PC工作站上工作时,这很有用。但你知道的。你正在使用只被一个应用程序使用的库。
[1]各个库文件的内存差异很小。共享库添加了一个索引和符号表,以便dlopen(3)可以加载库。这是否重要将取决于您的用例;为每个编译并比较大小以确定哪个在Flash中更小。您将不得不运行和分析以确定哪个消耗更多RAM;它们应该类似,除了共享库的初始加载。

1

拥有大量的库当然意味着需要存储更多的元数据,而且其中一些元数据(库部分标题等)在加载时需要存储在RAM中。但是差异应该是相当可忽略的,即使在(适度现代的)嵌入式系统上也是如此。

我建议您尝试两种替代方案,并测量FLASH和RAM中使用的空间,然后决定哪种最好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接