包含库的运行时性能成本是多少?

时间:2016-05-02 13:41:34

标签: c++ c performance include

在包含整个库(可能包含数百个函数)之间是否存在任何运行时性能差异,然后仅使用单个函数:

#include<foo>

int main(int argc, char *argv[]) {
    bar();//from library foo
    return 0;
}

将库中的相关代码片段直接粘贴到代码中,例如:

void bar() {
...
}

int main(int argc, char *argv[]) {
    bar();//defined just above
    return 0;
}

什么会阻止我在我的C文件开头无意识地包括我最喜欢的(也是最常用的)库?这个流行的帖子C/C++: Detecting superfluous #includes?表明编译时间会增加。但编译后的二进制文件会有什么不同吗?第二个程序实际上是否会优于第一个程序?

相关:what does #include <stdio.h> really do in a c program

编辑:此处的问题与相关的Will there be a performance hit on including unused header files in C/C++?问题不同,因为此处包含单个文件。我在这里问,如果包含单个文件与将实际使用的代码片段复制粘贴到源中有任何不同。我稍微调整了标题以反映这种差异。

4 个答案:

答案 0 :(得分:10)

就最终节目而言,没有性能差异。链接器仅链接实际用于程序的函数。库中存在的未使用的函数将无法链接。

如果包含大量库,则编译程序可能需要更长的时间。

你不应该包括你最喜欢的所有图书馆的主要原因是什么?是程序设计。您的文件不应包含除正在使用的资源之外的任何内容,以减少文件之间的依赖关系。你的文件对程序其余部分的了解越少越好。它应该尽可能自主。

答案 1 :(得分:6)

这不是一个简单的问题,所以不值得一个简单的答案。在确定什么是更高效的时候,您可能需要考虑许多事项。

  1. 您的编译器和链接器:不同的编译器将以不同的方式进行优化。这是容易被忽视的事情,并且在进行概括时可能会导致一些问题。在大多数情况下,现代编译器和链接器将优化二进制文件,仅包含执行所需的100%。但是并非所有编译器都会优化您的二进制文件。
  2. 动态链接:使用其他库时,有两种类型的链接。他们的行为方式类似,但根本不同。当您链接到动态库时,库将与程序保持独立,并且仅在运行时执行。动态库通常称为共享库,因此应被视为多个二进制文件使用它们。由于这些库通常是共享的,因此链接器不会从库中删除任何功能,因为链接器不知道该系统或操作系统中所有二进制文件将需要该库的哪些部分。因此,与动态库链接的二进制文件将会有很小的性能损失,尤其是在启动程序之后。随着动态链接的数量,这种性能提升将会增加。
  3. 静态链接:当您将二进制文件与静态库(使用优化链接器)链接时,链接器将“知道”#39;您将从该特定库中获得哪些功能,并将删除不会在生成的二进制文件中使用的功能。因此,二进制文件将变得更有效,因此性能更高。然而,这需要付出代价。

    <强> e.g。

    假设您有一个操作系统,它在整个系统中的大量二进制文件中广泛使用库。如果您要将该库构建为共享库,则所有二进制文件将共享该库,同时可能使用不同的功能。现在假设您将每个二进制文件静态链接到库。您最终会得到大量重复的二进制功能,因为每个二进制文件都需要从该库中获得所需功能的副本。

  4. 结论:值得注意的是,在提出问题之前,什么会使我的程序更高效,你应该问自己在你的情况下哪些更有效率。您的程序是否占用了大部分CPU时间,可能需要使用静态链接库。如果您的程序只是偶尔运行,可能需要动态链接库以减少磁盘使用量。值得注意的是,使用基于标头的库只能为静态链接二进制文件提供非常边缘(如果有的话)性能增益,并且会大大增加编译时间。

答案 2 :(得分:2)

它在很大程度上取决于库以及它们的结构,以及编译器实现的可能性。

链接器(ld)将只汇集代码引用的库中的代码,因此如果库中有两个函数ab,但只有对a的引用然后函数b可能根本不在最终代码中。

头文件(包含),如果它们只包含声明,并且如果声明没有导致对库的引用,那么在键入你需要的部分之间你看不出任何区别(根据你的例子)和包括整个头文件。

从历史上看,链接器ld会根据文件提取代码,因此当创建库时,每个函数ab都在不同的文件中,因此不会产生任何影响一点都不。

但是,如果没有仔细构建库,或者编译器实现确实从lib中提取了每一位代码,那么你可能会产生性能影响,因为你的代码会更大并且可能是更难以适应CPU缓存,并且CPU执行管道必须偶尔等待从主存储器而不是从缓存中获取指令。

答案 3 :(得分:0)

这在很大程度上取决于相关的图书馆。

他们可能会初始化全局状态,这会降低程序的启动和/或关闭速度。或者他们可能会启动与您的代码并行执行某些操作的线程。如果您有多个线程,这也可能会影响性能。

有些库甚至可能会修改现有的库函数。也许收集有关内存或线程使用情况的统计信息或用于安全审计目的。