Elo*_*off 382 c c++ performance dynamic-linking static-linking
在某些情况下,是否有任何令人信服的性能原因选择静态链接而不是动态链接?我已经听过或读过以下内容,但我对这个问题的了解不足以保证它的真实性.
1)静态链接和动态链接之间的运行时性能差异通常可以忽略不计.
2)(1)如果使用使用配置文件数据优化程序热路径的配置文件编译器,则不成立,因为使用静态链接,编译器可以优化代码和库代码.通过动态链接,您的代码可以进行优化.如果大部分时间都花在运行库代码上,那么这可能会产生很大的不同.否则,(1)仍然适用.
dmc*_*kee 339
一些编辑在评论和其他答案中包含非常相关的建议.我想指出,你打破这种方式的方式很大程度上取决于你计划运行的环境.最小的嵌入式系统可能没有足够的资源来支持动态链接.略大的小型系统可能很好地支持链接,因为它们的内存足够小,可以使动态链接节省的RAM非常有吸引力.正如马克指出的那样,全面的消费者电脑拥有巨大的资源,你可能会让便利问题引发你对这件事的思考.
解决性能和效率问题:取决于.
传统上,动态库需要某种粘合层,这通常意味着在函数寻址中需要双重调度或额外的间接层,并且可能会花费一点速度(但函数调用时间实际上是运行时间的一小部分???).
但是,如果您正在运行多个进程,这些进程都会大量调用同一个库,那么在使用静态链接相对使用动态链接时,最终可以保存缓存行(从而赢得运行性能).(除非现代操作系统足够聪明,能够注意到静态链接二进制文件中的相同段.看起来很难,有人都知道吗?)
另一个问题:加载时间.您在某个时候支付装载成本.支付此费用取决于操作系统的工作方式以及您使用的链接.也许你宁愿推迟支付,直到你知道你需要它为止.
请注意,静态与动态链接传统上不是优化问题,因为它们都涉及单独编译到目标文件.但是,这不是必需的:编译器原则上可以"初始化"将"静态库""编译"为消化的AST形式,并通过将这些AST添加到为主代码生成的AST来"链接"它们,从而赋予全局优化权限.我使用的系统都没有这样做,所以我不能评论它的工作情况.
回答性能问题的方法总是通过测试(并尽可能像部署环境一样使用测试环境).
Lot*_*har 67
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没有AFAIK用于其他任何东西,然后是15位跳转范围而不是无条件跳转和调用.这就是为什么具有超过32K的功能(来自发电机)一直是一个问题,需要嵌入式蹦床.
但是在流行的x86操作系统(如Linux)上,您根本不需要关心是否使用gcc交换机生成SO/DLL文件-fpic(强制使用间接跳转表).因为如果不这样做,代码就像普通链接器一样重新定位.但是在执行此操作时,它会使代码段不可共享,并且需要将代码从磁盘完全映射到内存并在使用它之前将其全部触摸(清空大多数缓存,触及TLB)等.有一段时间当这被认为是缓慢的......太慢了.
所以你不会再有任何好处了.
我不记得什么操作系统(Solaris或FreeBSD的)给我的问题,我的Unix编译系统,因为我只是不这样做的,不知道为什么它坠毁,直到应用我-fPIC来gcc.
Mar*_*som 65
动态链接是满足某些许可要求(如LGPL)的唯一实用方法.
sta*_*ica 44
我同意dnmckee提到的观点,加上:
Rob*_*lls 32
执行静态链接构建的一个原因是验证您是否已完全关闭可执行文件,即正确解析所有符号引用.
作为使用持续集成构建和测试的大型系统的一部分,夜间回归测试使用可执行文件的静态链接版本运行.偶尔,我们会看到符号无法解析,即使动态链接的可执行文件成功链接,静态链接也会失败.
这通常发生在共享库中深处的符号具有拼写错误的名称,因此不会静态链接.无论使用深度优先或广度优先评估,动态链接器都不会完全解析所有符号,因此您可以使用没有完全关闭的动态链接可执行文件.
APr*_*mer 21
1 /我一直在进行动态链接与静态链接进行基准测试的项目,并且确定差异不足以切换到动态链接(我不是测试的一部分,我只知道结论)
2 /动态链接通常与PIC(位置无关代码,与根据加载地址无需修改的代码)相关联.取决于体系结构,PIC可能带来另一个减速但是为了获得在两个可执行文件之间共享动态链接库的好处(如果OS使用加载地址的随机化作为安全措施,则甚至是相同可执行文件的两个进程).我不确定所有操作系统是否允许将这两个概念分开,但是Solaris和Linux确实可以和HP-UX一样.
3 /我参与了其他使用动态链接进行"简单补丁"功能的项目.但是这个"简单的补丁"使得小修补程序的分发变得更容易,并且复杂的版本化噩梦.我们经常最终必须推送所有内容以及必须跟踪客户站点的问题,因为错误的版本是令牌.
我的结论是我使用静态链接除外:
对于像依赖动态链接的插件这样的东西
当共享很重要时(多个进程同时使用的大型库,如C/C++运行时,GUI库,......通常是独立管理的,并且严格定义了ABI)
如果想要使用"简单补丁",我认为库必须像上面的大型库一样进行管理:它们必须几乎独立于定义的ABI,不能通过修复来改变.
Jon*_*ler 10
在类Unix系统上,动态链接可能使"root"生活变得困难,因为应用程序使用安装在偏远位置的共享库.这是因为动态链接器通常不会关注具有root权限的进程的LD_LIBRARY_PATH或其等价物.有时,静态链接可以节省一天.
或者,安装过程必须找到库,但这可能使多个版本的软件难以在机器上共存.
Static linking 是编译时将链接内容复制到主二进制文件并成为单个二进制文件的过程。
缺点:
Dynamic linking是加载链接内容时运行时的进程。该技术允许:
ABI稳定性[关于]缺点:
动态链接的最佳示例是,当库依赖于使用的硬件时.在古代,C数学库被认为是动态的,因此每个平台都可以使用所有处理器功能来优化它.
一个更好的例子可能是OpenGL.OpenGl是一种由AMD和NVidia以不同方式实现的API.并且您无法在AMD卡上使用NVidia实施,因为硬件不同.因此,您无法将OpenGL静态链接到您的程序中.此处使用动态链接来使API针对所有平台进行优化.
小智 6
静态链接将程序需要的文件包含在单个可执行文件中。
动态链接是您通常认为的,它使可执行文件仍然需要 DLL 并且位于同一目录中(或者 DLL 可能位于系统文件夹中)。
(DLL =动态链接库)
动态链接的可执行文件编译速度更快,并且不会占用大量资源。
尚未讨论的另一个问题是修复库中的错误.
使用静态链接,您不仅需要重建库,还必须重新链接并重新分发可执行文件.如果库只是在一个可执行文件中使用,这可能不是问题.但是需要重新链接和重新分配的可执行文件越多,痛苦就越大.
通过动态链接,您只需重建和重新分发动态库即可.