标头包含性能

Header Inclusion Performance

本文关键字:性能 包含      更新时间:2023-10-16

我经常避免只使用一个函数而包含大型头文件,认为这样做会降低性能。因此,我只需在代码中实现该函数,它将按预期工作。

最后,我意识到这几乎破坏了图书馆的整个概念,尽管很耗时。

考虑到这一点,C 编译器倾向于将程序动态链接到 libc 共享库(您可以使用命令查看哪些库是动态链接的:ldd (。那么,这是否意味着链接到整个库足够消耗性能,以至于我不需要关心单个文件包含?

可执行文件是否倾向于包含整个库函数,还是仅包含使用的函数?
我想知道是否有任何C/C++差异..

"所以,这是否意味着链接到整个库足够消耗性能,以至于我不需要关心单个文件包含?">

我不完全明白,你在哪里看到这里的性能问题。包括头文件由c预处理器优化,链接是不同的阶段,由链接器优化。
尽管通常有充分的理由,只是使用函数或类的前向声明,而不是包含整个标头。但这与性能无关。

"可执行文件倾向于包含整个库函数,还是只包含使用的功能?">

如果使用静态链接,链接器将仅添加已使用的函数。

"我想知道是否有任何C/C++差异..">

不。

添加到 πάντα ῥεῖ 的答案中:

  • 包含头文件在运行时没有任何成本。包含头文件将导致预处理器将头文件的内容转储到程序包含头文件的位置。C 头文件不包含导致编译器在包含它们时发出代码的任何内容。虽然标头可以这样做,但这被认为是不良风格并且不受欢迎。

  • 在使用ELF作为二进制文件的系统(Linux,BSD,Solaris,Unix等(上,除了具有static链接的函数之外,每个函数都通过PLT调用。这是一个表,其中包含每个可以调用的函数的小代码存根。程序启动时,PLT 仅包含占位符。第一次调用函数时,链接器会解析其地址并替换 PLT 中的代码,以便对该函数的下一次调用不会通过链接器,并且实际上不会比不通过 PLT 的调用慢得多。额外费用是一次跳跃指令。

  • 程序启动时,链接器会将程序依赖的所有库加载到进程的地址空间中。这并不意味着库实际上将从硬盘读取;操作系统只从硬盘中读取实际需要的部分。

  • 可以告诉链接器仅在调用库中的第一个函数后加载库。这通常不是一件好事,但在极少数用例中,这是有意义的,例如拥有一个可以在您要使用的库不可用的环境中使用的程序。

  • 不要太担心动态库的开销。它可以忽略不计,除非在极端情况下,否则根本不重要。在优化这些内容之前执行测量。