普遍认为静态库的性能优于动态库。我的问题是:这是否也取决于dll加载到内存中的时间?我的意思是,一旦初始化和所有操作都完成了,调用和执行函数在动态库中是否比静态库需要更长的时间?
哦,我提供的链接是以 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收益大一个数量级。)
我认为,就性能而言,静态库与动态库最大的区别在于编译器可以对静态库中的函数调用进行优化,但是对于动态库,编译器无法得知其调用的函数行为。
在 DLL 或静态库中,机器码本身具有相同的性能。然而编译器可以更积极地优化使用静态库的可执行文件,特别是当启用链接时代码生成时。可以考虑删除未使用的变量和重复代码并将一起使用的代码放置在靠近彼此的位置(参见 PGO)。
当代码在多个应用程序之间共享时,从系统性能角度来看最好使用系统提供的 DLL,因为系统的整体内存压力较小(当操作系统能够在进程之间映射内存部分视图时,Windows 就是这样做的)。
linux
。你的环境具体是什么样子的? - Asaph