|
|
1
323
一些编辑将非常相关的建议包括在评论和其他答案中。我想指出的是,你在这方面的突破很大程度上取决于你计划在什么环境中运行。最小的嵌入式系统可能没有足够的资源来支持动态链接。稍大一点的小型系统可能很好地支持链接,因为它们的内存足够小,使得动态链接节省的RAM非常有吸引力。正如马克所指出的,全套消费型PC拥有巨大的资源,你可能会让便利性问题驱使你思考这个问题。 要解决性能和效率问题: 它取决于 . 传统上,动态库需要某种粘合层,这通常意味着在函数寻址中需要双重调度或额外的一层间接寻址,并且可能需要一点速度(但是函数调用时间实际上是运行时间的很大一部分吗???). 但是,如果您运行的多个进程都调用了同一个库,那么在使用动态链接(相对于静态链接)时,可以最终保存缓存线(从而赢得运行性能)。(除非现代操作系统足够聪明,能够注意到静态链接的二进制文件中相同的段。似乎很难,有人知道吗?) 另一个问题:装载时间。在某个时候你要付装货费。当你支付这个费用时,这取决于操作系统的工作方式以及你使用的链接。也许你宁愿推迟付款直到你知道你需要它。 注意,静态与动态链接是传统的 不 一个优化问题,因为它们都涉及到对象文件的单独编译。但是,这不是必需的:原则上,编译器可以先将“静态库”编译为消化的ast形式,然后通过将这些ast添加到为主代码生成的ast中来“链接”它们,从而实现全局优化。我使用的所有系统都没有这样做,所以我无法评论它的工作情况。 回答绩效问题的方法是 总是 通过测试(并尽可能使用与部署环境相似的测试环境)。 |
|
|
2
63
动态链接是满足某些许可证要求(如 LGPL . |
|
|
3
63
1)基于调用dll函数总是使用额外的间接跳转这一事实。今天,这通常可以忽略不计。在动态链接库中,i386 CPU的开销更大,因为它们不能生成位置无关的代码。在AMD64上,跳转可以相对于程序计数器,所以这是一个巨大的改进。 2)这是正确的。通过分析引导的优化,您通常可以获得大约10-15%的性能。既然CPU速度已经达到了极限,那么做可能是值得的。 我想补充一点:(3)链接器可以将函数安排在一个更高效的缓存分组中,这样就可以将昂贵的缓存级别未命中最小化。它还可能特别影响应用程序的启动时间(基于我在Sun C++编译器上看到的结果) 别忘了,有了动态链接库,就不能执行死代码消除。根据语言的不同,DLL代码也可能不是最佳的。虚拟函数总是虚拟的,因为编译器不知道客户端是否正在覆盖它。 出于这些原因,如果不需要DLL,那么只需使用静态编译。 编辑(按用户下划线回答注释) 这里有一个关于位置无关代码问题的好资源 http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/ 正如所解释的那样,x86没有任何其他15位跳转范围的afaik,也没有无条件跳转和调用。这就是为什么功能(来自发电机)超过32K一直是一个问题,需要嵌入蹦床。
但在流行的x86操作系统(如Linux)上,您不需要关心是否使用
所以你再也没有任何好处了。
我不记得操作系统(solaris或freebsd)给我的Unix构建系统带来了什么问题,因为我没有这样做,我想知道为什么它会崩溃,直到我应用
|
|
|
4
42
我同意dnmckee提到的观点,加上:
|
|
|
5
31
执行静态链接构建的一个原因是验证可执行文件是否完全关闭,即所有符号引用是否正确解析。 作为正在使用连续集成构建和测试的大型系统的一部分,使用静态链接版本的可执行文件运行夜间回归测试。偶尔,我们会看到符号无法解析,静态链接也会失败,即使动态链接的可执行文件链接成功。 这种情况通常发生在那些深埋在共享libs中的符号有一个拼写错误的名称,因此不会静态链接的时候。动态链接器不会完全解析所有符号,不管使用深度优先还是宽度优先评估,因此您可以使用没有完全关闭的动态链接可执行文件来完成。 |
|
|
6
21
1/我曾参与过一些项目,其中动态链接与静态链接是基准,但差异还没有确定到足以转换为动态链接的程度(我不是测试的一部分,我只是知道结论)。 2/动态链接通常与pic(位置无关代码,不需要根据加载地址修改的代码)相关。根据体系结构的不同,pic可能会带来另一种减速,但为了在两个可执行文件之间共享动态链接库(如果操作系统使用随机加载地址作为安全措施,甚至是同一个可执行文件的两个进程),需要pic。我不确定所有的操作系统都允许将这两个概念分开,但是Solaris和Linux也允许HP-UX将这两个概念分开。 3/我还参与过其他项目,这些项目使用了“轻松补丁”功能的动态链接。但是这个“简单补丁”使得小补丁的分发变得更加简单,而复杂补丁的分发则是版本控制的噩梦。我们经常不得不推送所有东西,还要跟踪客户站点的问题,因为错误的版本是令牌。 我的结论是我使用了静态链接,除了:
如果有人想使用“简单补丁”,我会认为库必须像上面的大型库一样进行管理:它们必须几乎独立于一个定义好的ABI,不能通过修复来更改。 |
|
8
10
在类Unix的系统上,动态链接可能会使“根”使用安装在偏远位置的共享库的应用程序变得困难。这是因为对于具有根权限的进程,动态链接器通常不会注意ld_library_path或其等效项。有时候,静态链接可以节省一天的时间。 或者,安装过程必须找到库,但这会使多个版本的软件难以在计算机上共存。 |
|
9
10
这很简单,真的。当您对源代码进行更改时,您希望等待10分钟以生成它还是等待20秒?我只能忍受20秒。除此之外,我要么拿出剑来,要么开始思考如何使用单独的编译和链接将它带回到舒适区。 |
|
|
10
7
动态链接需要额外的时间让操作系统找到动态库并加载它。通过静态链接,所有东西都在一起,这是对内存的一次性加载。 此外,参见 DLL Hell . 在这种情况下,OS加载的dll不是应用程序附带的dll,也不是应用程序期望的版本。 |
|
|
11
7
动态链接的最佳示例是,当库依赖于使用的硬件时。在古代,C数学库被认为是动态的,因此每个平台都可以使用所有处理器功能来优化它。 一个更好的例子可能是OpenGL。OpenGL是一个API,由AMD和Nvidia以不同的方式实现。而且你不能在AMD卡上使用NVIDIA实现,因为硬件是不同的。因此,不能将OpenGL静态链接到程序中。这里使用动态链接来为所有平台优化API。 |
|
|
12
5
另一个尚未讨论的问题是修复库中的错误。 使用静态链接,您不仅需要重建库,还必须重新链接并重新分配可执行文件。如果库只在一个可执行文件中使用,这可能不是问题。但是需要重新链接和重新分配的可执行文件越多,痛苦就越大。 通过动态链接,只需重新构建和重新分配动态库,即可完成。 |
|
|
13
3
静态链接只提供一个exe,为了进行更改,需要重新编译整个程序。而在动态链接中,您只需要更改dll,当您运行exe时,这些更改将在运行时被获取。通过动态链接(例如:Windows)更容易提供更新和错误修复。 |
|
|
14
2
有大量且越来越多的系统,其中极端水平的静态链接会对应用程序和系统性能产生巨大的积极影响。 我指的是通常被称为“嵌入式系统”的系统,其中许多系统现在越来越多地使用通用操作系统,而这些系统被用于一切可以想象到的事情。
一个非常常见的例子是使用GNU/Linux系统的设备
Busybox
.我把这个带到了极端
NetBSD
通过构建一个可引导的i386(32位)系统映像,其中包含内核及其根文件系统,后者包含一个静态链接
在前面的文章中已经提到,静态链接二进制文件的启动时间更快(它可以是
许多
更快),但这只是图片的一部分,尤其是当所有对象代码都链接到同一个文件时,尤其是当操作系统支持直接从可执行文件请求代码分页时。在这个理想的场景中,程序的启动时间是
字面
可以忽略不计,因为几乎所有的代码页都已经在内存中,并且被shell使用(和
然而,这还不是全部。我还通常通过静态链接所有二进制文件,为我的完整开发系统构建和使用netbsd操作系统安装。尽管这会占用大量的磁盘空间(对于x86_64,包括toolchain和x11静态链接在内的所有程序,总共约6.6GB)(尤其是如果一个程序保持完整的调试符号表可供所有程序使用,另一个约2.5GB),但总体而言,结果仍然运行得更快,对于某些任务,甚至比典型的动态链接系统占用更少的内存。声称共享库代码页的STEM。磁盘是便宜的(甚至是快磁盘),内存缓存频繁使用的磁盘文件也是相对便宜的,但CPU的周期确实不是,而且支付
|
|
|
15
1
静态链接包括程序在单个可执行文件中需要的文件。 动态链接是您通常认为的,它使可执行文件仍然需要dlls,并且这样的文件在同一目录中(或者dlls可能在系统文件夹中)。 (DLL= 动态链接 图书馆) 动态链接的可执行文件的编译速度更快,资源也不那么重。 |