在某些情况下,选择静态链接而不是动态链接或反之,是否有令人信服的性能原因?我听过或读过以下内容,但我对这个主题了解不够,无法保证其真实性。

1)静态链接和动态链接在运行时性能上的差异通常可以忽略不计。

如果使用使用概要数据优化程序热路径的分析编译器,2)(1)是不正确的,因为使用静态链接,编译器可以优化你的代码和库代码。使用动态链接,只能优化您的代码。如果大部分时间都花在运行库代码上,这可能会有很大的不同。否则,(1)仍然适用。


当前回答

静态链接将程序需要的文件包含在一个可执行文件中。

动态链接是你通常会考虑的,它使一个可执行文件仍然需要dll等在同一个目录(或者dll可以在系统文件夹中)。

(动态链接库)

动态链接的可执行文件编译速度更快,资源也不那么繁重。

其他回答

动态链接的最佳示例是库依赖于所使用的硬件。在古代,C数学库是动态的,这样每个平台都可以使用所有的处理器功能来优化它。

一个更好的例子可能是OpenGL。OpenGl是一个由AMD和NVidia实现的不同的API。你不能在AMD卡上使用NVidia实现,因为硬件是不同的。因此,你不能静态地将OpenGL链接到你的程序中。这里使用了动态链接,以便为所有平台优化API。

1)基于这样一个事实,即调用DLL函数总是使用额外的间接跳转。如今,这通常可以忽略不计。在DLL内部,i386 CPU上有一些更多的开销,因为它们不能生成与位置无关的代码。在amd64上,跳转可以相对于程序计数器,因此这是一个巨大的改进。

2)这是正确的。通过分析引导的优化,您通常可以获得大约10- 15%的性能。既然CPU速度已经达到极限,那么这样做可能是值得的。

我想补充的是:(3)链接器可以将函数安排在一个更有效的缓存分组中,从而将昂贵的缓存级别的失败最小化。它还可能特别影响应用程序的启动时间(基于我在Sun c++编译器中看到的结果)

不要忘记,使用dll不能执行死代码消除。根据语言的不同,DLL代码也可能不是最佳的。虚函数总是虚函数,因为编译器不知道客户端是否正在覆盖它。

由于这些原因,如果不需要dll,那么就使用静态编译。

编辑(通过用户下划线回答注释)

这里有一个关于职位独立代码问题的很好的资源http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/

正如所解释的,x86除了15位跳转范围之外没有其他的AFAIK,也没有无条件跳转和调用。这就是为什么函数(来自生成器)超过32K一直是一个问题,需要嵌入蹦床。

But on popular x86 OS like Linux you do not need to care if the .so/DLL file is not generated with the gcc switch -fpic (which enforces the use of the indirect jump tables). Because if you don't, the code is just fixed like a normal linker would relocate it. But while doing this it makes the code segment non shareable and it would need a full mapping of the code from disk into memory and touching it all before it can be used (emptying most of the caches, hitting TLBs) etc. There was a time when this was considered slow.

这样你就没有任何收益了。

我不记得什么操作系统(Solaris或FreeBSD)给我的Unix构建系统的问题,因为我只是没有这样做,不知道为什么它崩溃,直到我应用-fPIC到gcc。

1/我曾经参与过一个项目,其中动态链接和静态链接是基准测试,差异并没有小到可以切换到动态链接(我没有参与测试,我只知道结论)

2/ Dynamic linking is often associated with PIC (Position Independent Code, code which doesn't need to be modified depending on the address at which it is loaded). Depending on the architecture PIC may bring another slowdown but is needed in order to get benefit of sharing a dynamically linked library between two executable (and even two process of the same executable if the OS use randomization of load address as a security measure). I'm not sure that all OS allow to separate the two concepts, but Solaris and Linux do and ISTR that HP-UX does as well.

3/我在其他项目中使用了动态链接的“简单补丁”功能。但是这个“简单补丁”使得小补丁的发布更加容易,而复杂补丁的发布则成为版本控制的噩梦。因为错误的版本是token,我们经常不得不推送所有内容,并在客户站点跟踪问题。

我的结论是,我使用静态链接除外:

比如依赖于动态链接的插件 当共享是重要的(大型库被多个进程同时使用,如C/ c++运行时,GUI库,…它们通常是独立管理的,ABI对此有严格的定义)

如果有人想使用“简单的补丁”,我认为库必须像上面的大库一样管理:它们必须几乎独立,具有定义好的ABI,不能被修复更改。

我同意dnmckee提到的观点,另外:

静态链接的应用程序可能更容易部署,因为很少或没有额外的文件依赖项(.dll / .so),当它们丢失或安装在错误的位置时,可能会导致问题。

动态链接是满足某些许可要求(如LGPL)的唯一实用方法。