共享对象开销

时间:2011-10-19 11:44:44

标签: c linux embedded shared-libraries

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

您对此有何看法?

最诚挚的问候,

3 个答案:

答案 0 :(得分:7)

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

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

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

  • 丢失一个通用寄存器(这在x86(32位)上可能很大,但在其他拱门上大多不相关)。
  • 访问全局/静态变量(和常量)的额外级别的间接访问。

如果您有一个长期运行的大型应用程序,那么成本可能对您来说无关紧要,除非您使用的是小型嵌入式系统。另一方面,如果您正在编写可以多次调用的短期任务(如语言解释器),这些成本可能会很高。将所有标准模块放在他们自己的.so文件中而不是默认情况下静态链接它们是Perl,Python等开始这么慢的原因的很大一部分。

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

答案 1 :(得分:5)

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

您需要考虑的另一个因素是性能损失。打开共享库需要很少的时间(通常是微不足道的);如果您的处理器速度非常慢或实时性要求很高,则静态库不会导致共享库的负载损失。通过配置文件查找这是否重要。

总之,在某些特殊情况下,共享库可能明显优于静态库。在大多数情况下,它们几乎没有伤害。在简单的情况下,您无法从共享库中获益。


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


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

答案 2 :(得分:1)

当然,拥有大量库意味着必须存储更多的元数据,并且在加载时还需要将一些元数据(库部分标题等)存储在RAM中。但即使在(适度现代的)嵌入式系统上,差异也应该是微不足道的。

我建议您尝试两种方法,并测量FLASH和RAM中的已用空间,然后确定哪种方式最佳。