静态库与动态库的性能比较

14

普遍认为静态库的性能优于动态库。我的问题是:这是否也取决于dll加载到内存中的时间?我的意思是,一旦初始化和所有操作都完成了,调用和执行函数在动态库中是否比静态库需要更长的时间?


你在询问关于DLL的问题,但是你的问题标记为linux。你的环境具体是什么样子的? - Asaph
你使用的是Linux还是Windows?共享库和位置无关代码系统非常不同。Windows DLL在Linux意义上不是位置无关的,尽管它们可以被重定位。 - Yann Ramin
3个回答

23
免责声明:我是一个 Linux-fu 新手,所以可能有些不准确的地方(或者说到处都是不准确的地方)。但是总体思路应该相对正确。如果不正确,我相信好心的 SO 社区会很快纠正我。 :-)

哦,我提供的链接是以 Windows 为中心的。如果有人能提供适当的 Linux 链接,我将不胜感激。

简短回答:可能会。然而,即使是这样,性能差异也非常微不足道。

当你链接静态库时,编译器生成代码直接进行所有函数调用。当进程被创建并执行该代码时,函数调用是一个简单的调用指令。

当你使用动态库时,成本取决于你是否使用装载时动态链接运行时动态链接

使用装载时动态链接时,编译器仍然生成代码直接调用函数,就像静态链接一样。当进程加载 DLL 时,它将调用运行时链接器来修复进程内存,以便这些调用直接到达实际的函数实现。这必须在从已加载的库中调用任何函数之前发生。在 Windows 上,它由 NT DLL 加载器完成,在进程初始化时调用 DLL 的 LoadLibrary。在 Linux 上,它由运行时链接器 ld-linux.so 完成。

使用 /DELAYLOAD 延迟加载链接,过程基本相同,只是编译器生成调用小存根的代码,存根将检查库是否已加载,如果未加载,则调用NT DLL加载程序。因此,DLL将按需加载,进程加载器不必在进程初始化时加载它。这导致更快的进程启动时间,但调用性能仍然相同。(但请注意,延迟加载存在其他缺点)

我不知道Linux是否有相应的支持,但如果没有,我会感到惊讶。

使用 运行时动态链接,您的代码维护函数指针并决定何时dload库。在Windows上,它必须使用LoadLibrary和GetProcAddress,在Linux上则是dlopen、dlsym和dlclose。无论哪种情况,对于进程启动时间的影响与延迟加载的 延迟加载链接 相同; 然而,每个方法调用的指针解引用确实增加了一些可忽略的成本。(尽管如果您知道自己在做什么,您可以疯狂地修复您的进程内存以避免指针解引用。然而,正确执行此操作的工作量比进行此操作获得的perf收益大一个数量级。)


2
耶,我的第一个严肃的与Linux相关的回答!欢迎点踩,但请告诉我哪里错了! :-) - Franci Penov

10

我认为,就性能而言,静态库与动态库最大的区别在于编译器可以对静态库中的函数调用进行优化,但是对于动态库,编译器无法得知其调用的函数行为。


0

在 DLL 或静态库中,机器码本身具有相同的性能。然而编译器可以更积极地优化使用静态库的可执行文件,特别是当启用链接时代码生成时。可以考虑删除未使用的变量和重复代码并将一起使用的代码放置在靠近彼此的位置(参见 PGO)。

当代码在多个应用程序之间共享时,从系统性能角度来看最好使用系统提供的 DLL,因为系统的整体内存压力较小(当操作系统能够在进程之间映射内存部分视图时,Windows 就是这样做的)。


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