在我正在研究的嵌入式设备上,启动时间是一个重要问题。整个应用程序由几个使用一组库的可执行文件组成。由于FLASH内存空间有限,我们希望使用共享库。
应用程序在编译和链接共享库时照常工作,并且FLASH内存量按预期减少。 与静态库链接的版本的不同之处在于应用程序的启动时间大约长达20秒,我不知道为什么。
该应用程序使用Linux 2.6.17操作系统在180 MHz的ARM9 CPU上运行, 16 MB FLASH(JFFS文件系统)和32 MB RAM。
答案 0 :(得分:7)
Bacause共享库必须在运行时链接,通常是通过dlopen()或类似的东西。静态库没有这样的步骤。
编辑:更详细一些。 dlopen必须执行以下任务。
这需要完成很多IO操作。
在静态链接程序中,以上所有操作都是在编译时完成的,而不是运行时。因此,加载静态链接程序要快得多。
在您的情况下,您的代码必须运行相对较慢的硬件会夸大差异。
答案 1 :(得分:4)
这是速度与空间经典权衡的一个很好的例子。
您可以静态链接所有可执行文件,以便它们更快,但随后它们将占用更多空间
或强>
您可以拥有占用更少空间但也有更多时间加载的共享库。
所以决定你要牺牲什么。
这种差异有许多因素(OS,编译器e.t.c),但可以找到一个很好的理由列表here。基本上共享库是出于空间原因而创建的,并且使它们工作所涉及的大部分“魔法”都会受到性能影响。
(作为历史记录,Linux / Unix上的原始Netscape导航器是静态链接的大型可执行文件)。
答案 2 :(得分:2)
这可能有助于其他有类似问题的人:
在我的情况下启动花了这么长时间的原因是,GCC的默认设置是导出库中的所有符号。 一个很大的改进是设置编译器设置“-fvisibility = hidden”。
必须使用语句
扩充lib必须导出的所有符号 __attribute__ ((visibility("default")))
答案 3 :(得分:1)
好的,我现在已经了解到共享库的使用对速度有不利影响。我发现这篇关于dynamic linking and loading启发的文章。装载过程似乎比我预期的要长得多。
答案 4 :(得分:0)
有趣的..通常,共享库的加载时间与静态链接的胖应用程序无法察觉。所以我只能猜测系统要么从闪存加载库要么很慢,要么以某种方式检查加载的库(例如.NET应用程序为所有加载的dll运行校验和,大大减少启动时间)一些案例)。可能是根据需要加载共享库,然后卸载,这可能表示配置问题。
所以,抱歉,我不禁说出原因,但我认为这是您的ARM设备/操作系统的问题。您是否尝试过检测启动代码,或者静态链接1个最常用的库,看看是否会产生很大的差异。还将共享库放在与应用程序相同的目录中,以减少搜索FS的库所需的时间。
答案 5 :(得分:0)
对我来说,一个显而易见的选择是将几个程序静态链接到一个二进制文件中。这样你就可以继续共享尽可能多的代码(可能比以前更多),但你也可以避免动态链接器的开销,并节省在系统上拥有动态链接器的空间。
将几个可执行文件组合到同一个可执行文件中非常容易,通常只需检查argv并根据该文件决定调用哪个例程。