2

假设缓冲区是一个由多个成员组成的结构,包括一个数组。

使用通常的优化标志进行编译,运行这两个代码片段应该会有什么样的性能差异?

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);
}

对比

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);
}
4

2 回答 2

3

第一个答案是:对它们进行基准测试。

第二个答案是:将它们编译为汇编语言,并查看源代码。在有和没有优化标志的情况下这样做可能是有启发性的。

正如 abelenky 所指出的,在这两种情况下buf都在堆栈上。我的一般猜测是第二种情况会稍微快一些(使用我使用的编译器),因为 buf 不必作为参数传递。它确实必须在堆栈上分配,但堆栈分配通常只是函数调用帧的大小略有不同。无论该帧有多大,都必须完成相同数量的工作(调整堆栈指针)。

所以我希望生成代码的主要区别是在第二种情况下少一条“PUSH”指令,假设有足够的参数必须进入堆栈。(如果它们都在寄存器中,那就有点不同了。)

它可能会受到优化的影响,例如是否buf在每种情况下都以寄存器结尾。但是填充 buf 的缺失代码可能会影响这一点,所以我不会推测。

请注意,以上是我基于查看编译器行为的猜测。理论上,只要生成的程序正确运行,编译器就可以按照他们喜欢的方式翻译代码,这使得很难概括他们可能会或可能不会做哪些优化。

于 2012-04-26T00:01:38.157 回答
0

@TJD 在他的评论中是正确的。

在这两种情况下,buf都在堆栈上,如果它很大,则有可能导致问题。您通常应该使用malloc.

也就是说,在您的第二个示例中,buf完全在init函数内部,并且在该函数返回给调用者的那一刻消失(在您的示例中调用者未命名)。

init实际上是无用的,因为完成的所有工作都丢失了,并且在调用函数中不可见。

在第一个示例中,返回buf后仍然有效init

于 2012-04-25T23:05:06.570 回答