一般认为静态库的性能大于动态库的性能。我的问题是:一旦dll已经加载到内存中,它还依赖于它吗?我的意思是,一旦初始化和所有事情发生,动态库的函数调用和执行是否比静态库需要更长的时间?
答案 0 :(得分:11)
免责声明:我是一名Linux-fu蚱蜢,因此可能存在一些不准确之处(或者只是到处都是)。但一般的想法应该是相对正确的。如果不是,我相信好的SO人会迅速纠正我。 : - )
哦,我提供的链接是以Windows为中心的。如果有人能提供正确的以Linux为中心的链接,我将不胜感激。
简短回答:可能。但是,即使这样,性能差异也可以忽略不计。
链接静态库时,编译器会生成代码以直接执行所有函数调用。创建进程并执行该代码时,函数调用是一个简单的调用指令。
使用动态库时,费用取决于您使用加载时动态链接还是运行时动态链接。
使用load-time dynamic linking,编译器仍会生成直接调用函数的代码,就好像它是静态链接的一样。当进程加载器加载DLL时,它将调用运行时链接程序来修复进程内存,以便这些调用直接进入实际的函数实现。这必须在从加载的库中调用函数之前发生。在Windows上,它由NT DLL加载器完成,它在进程初始化时调用DLL上的LoadLibrary。在Linux上,它由运行时链接程序ld-linux.so完成。
使用/DELAYLOAD
加载时动态链接,除了编译器生成调用小存根的代码之外,该进程基本相同,这将检查库是否已加载,以及是否不会,将调用NT DLL加载程序。因此,DLL将按需加载,并且进程加载器不必在进程初始化时加载它。这样可以加快进程启动时间,但通话性能仍然相同。 (但请注意,延迟负载存在其他缺点)
我不知道是否有相应的Linux支持,但如果没有,我会感到惊讶。
使用run-time dynamic linking,您的代码维护函数指针并决定何时卸载库。在Windows上,它必须使用LoadLibrary和GetProcAddress,在Linux上它是dlopen,dlsym和dlclose。在任何情况下,对进程启动时间的影响与延迟加载加载时动态链接相同;但是,在每个方法调用上取消引用的指针确实增加了一个可忽略不计的小成本。 (虽然如果你知道自己在做什么,你可能会疯狂并修复你的进程内存以避免指针解除引用。然而,这样做的努力比你获得的性能要好一个数量级。它)。
答案 1 :(得分:4)
我认为性能方面的最大区别在于,使用静态库,编译器可以优化对库的函数调用,但在动态库中,编译器对它调用的函数的行为一无所知。
答案 2 :(得分:0)
DLL或静态库中的机器代码本身具有相同的性能。编译器可以通过静态库更积极地优化可执行文件,尤其是在启用链接时代码生成时。可以考虑在一起使用时删除未使用的变量和重复的代码以及代码的放置(参见PGO)。
当跨应用程序共享代码时,最好从系统性能的角度使用DLL,因为系统的整体内存压力较小(当os能够映射内存部分的视图时跨越Windows的流程。