【问题标题】:Static vs. Dynamic Library Performance静态与动态库性能
【发布时间】:2011-05-22 01:10:43
【问题描述】:

一般认为静态库的性能优于动态库。我的问题是:它是否还取决于 dll 是否已加载到内存中?我的意思是,一旦初始化和所有事情都发生了,动态库的函数调用和执行时间会比静态库长吗?

【问题讨论】:

  • 您询问的是 DLL,但您的问题被标记为 linux。您的环境到底是什么样的?
  • 您使用的是 Linux 还是 Windows?共享库和位置无关的代码系统非常不同。 Windows DLL 在 Linux 意义上不是位置独立的,尽管它们可以重新定位

标签: windows dynamic static


【解决方案1】:

免责声明:我是 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。在任何情况下,进程启动时间的含义与延迟加载加载时间动态链接的含义相同;但是,每个方法调用上的指针取消引用确实增加了一个可以忽略不计的小成本。 (尽管如果您知道自己在做什么,您可能会发疯并修复您的进程内存以避免指针取消引用。但是,正确执行此操作的努力比您将获得的性能收益大一个数量级它。)

【讨论】:

  • 是的,我的第一个严肃的 Linux 相关答案!欢迎投反对票,但请告诉我我错在哪里! :-)
【解决方案2】:

我认为在性能方面最大的区别在于,对于静态库,编译器可以优化对库的函数调用,但在动态库中,编译器对其调用的函数的行为一无所知。

【讨论】:

    【解决方案3】:

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

    当跨应用程序共享代码时,从系统性能的角度来看,最好使用 DLL,因为系统的整体内存压力较小(当 os 能够映射内存部分的视图时) Windows 所做的跨进程)。

    【讨论】:

      猜你喜欢
      • 2011-11-05
      • 2011-09-12
      • 1970-01-01
      • 2013-07-20
      • 1970-01-01
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多