假设 buffer 是由几个成员组成的结构,包括一个数组。
使用通常的优化标记进行编译,运行这两个代码片段应该会产生什么样的性能差异?
buffer buf;
for (int i = 0; i < BIG_ENOUGH_NUMBER; i++) {
init(huge_file, i, &buf);
}
// buf is not used afterward
...
void init(FILE* f, int i, buffer* b) {
... // b is filled using f, according to i
do_something(b);
}
VS
for (int i = 0; i < BIG_ENOUGH_NUMBER; i++) {
init(huge_file, i);
}
...
void init(FILE* f, int i) {
buffer buf;
... // buf is filled from scratch using f, according to i
do_something(&buf);
}
答案 0 :(得分:3)
第一个答案是:基准测试。
第二个答案是:将它们编译为汇编语言,然后查看源代码。使用和不使用标志符号执行此操作可能具有指导意义。
正如所指出的那样,在两种情况下buf
都在堆栈中。我的一般猜测是,第二种情况会稍快一些(我用过的编译器),因为buf不必作为参数传递。它必须在堆栈上分配,但堆栈分配通常只是函数调用帧的略微不同。无论该帧有多大,都必须完成相同数量的工作(调整堆栈指针)。
所以我希望在第二种情况下生成的代码中的主要区别是少一个“PUSH”指令,假设有足够的参数,有些必须进入堆栈。 (如果它们都在寄存器中,那就有点不同了。)
它可能受到优化的影响,例如buf
在每种情况下是否都以寄存器结束。但缺少填充buf的代码可能会影响这一点,所以我不会推测。
请注意,基于查看编译器的行为,以上是我的猜测。从理论上讲,只要生成的程序运行正常,编译器就可以翻译代码,这使得很难概括他们可能做或不做的优化。
答案 1 :(得分:0)
@TJD的评论是正确的。
在这两种情况下,buf
都在堆栈中,如果它很大,则有可能导致问题。
您通常应使用malloc
从堆中分配大型项目。
那就是说,在你的第二个例子中,buf
完全在init
函数内部,并且在函数返回调用者的那一刻消失(调用者在你的例子中未命名)。
init
实际上没用,因为完成的所有工作都已丢失,并且在调用函数中不可见。
在第一个示例中,buf
在init
返回后仍然有效。