我一直在用Valgrind做一些测试来理解编译器如何翻译函数,并且发现有时,写在不同文件上的函数与写在同一源文件上的函数相比由于没有内联而表现不佳。
考虑到我有不同的文件,每个文件包含与特定区域相关的功能,所有文件共享一个公共标题,声明所有功能,这是预期的吗?
为什么编译器在不同文件上编写时会内联它们,但是当它们在同一页面上时呢?
如果此行为开始导致性能问题,建议的操作过程是什么,在编译之前手动将所有函数放在同一文件上?
示例:
//source 1
void foo(char *str1, char *str2)
{
//here goes the code
}
//source 2
void *bar(int something, char *somethingElse)
{
//bar code
foo(variableInsideBar, anotherVariableCreatedInsideBar);
return variableInsideBar;
}
示例性能成本:
在不同的文件:29920
两者都在同一个文件中:8704
对于更大的功能,它不是那么明显,但仍然会发生。
答案 0 :(得分:2)
如果您使用gcc
,则应尝试选项-combine
和-fwhole-program
,并在一次调用中将所有源文件传递给编译器。传统上不同的C文件是单独编译的,但优化交叉编译单元(文件)变得越来越普遍。
答案 1 :(得分:1)
编译器本身不能简单地内联在不同翻译单元中定义的函数,因为它无法看到这些函数的定义,即它无法看到这些函数的源代码。从历史上看,C编译器(以及语言本身)是围绕独立翻译的原则构建的。每个翻译单元从源代码编译到完全独立地形成其他翻译单元的目标代码。只有在翻译的最后阶段,所有这些不相交的目标代码片段才被所谓的链接器组合在一起成为最终的程序。但是在传统的编译器实现中,内联任何内容已经太晚了。
正如您可能知道的那样,对函数内联的语言级支持说,为了使函数在某些翻译单元中“无法”,它必须在该翻译单元中定义,即其内部的源代码应该是对于该翻译单元中的编译器是可见的。这一要求直接源于上述独立翻译原则。
许多现代编译器正在逐步引入克服经典纯独立翻译限制的功能。它们实现了全局优化等功能,允许跨越翻译单元边界的各种优化。这可能包括内联其他翻译单元中定义的函数的能力。请参阅编译器文档,以了解它是否可以跨翻译单元内联函数以及如何启用此类优化。
默认情况下,通常禁用此类全局优化的原因是它们可以显着增加转换时间。
答案 2 :(得分:-1)
我认为这不会花费太多的成本。