某些基本操作的CPU成本数量级

时间:2011-02-12 11:13:31

标签: c++ performance memory-management

在回答that SO question并被拒绝后,我想和你一起检查一下。

为了对我编写的代码的成本有一个草案,我倾向于以这种方式扩展操作。

  • 堆分配比堆栈分配慢大约1000倍。
  • 带屏幕/输出的IO约为1000次 比堆分配慢。
  • 硬盘上的IO大约慢1000倍 而不是屏幕上的图形IO。

您认为这是正确的假设/数量级/估计吗?

(当然,没有什么比真正的应用程序分析: - ))

编辑:根据您的回答和评论作为第一个结论,可以说我的数字1000 很大程度上高估了。

3 个答案:

答案 0 :(得分:5)

如果您要进行类似的大规模概括,您可能需要考虑使用硬数据进行备份。

我不怀疑你对大多数架构的相对效率是对的(我说的最简单,因为可能有一些奇怪的架构,我不知道)但是1000x比例在没有证据的情况下是可疑的。

实际上,我并非 确定屏幕和磁盘I / O的相对效率,因为它可能会受到缓冲的影响。我经常发现,在将输出定向到磁盘文件时,向屏幕输出数千行的程序运行得更快。

例如,以下程序:

#include <stdio.h>
int main (void) {
    int i;
    for (i = 100000; i > 0; i--)
        printf ("hello\n");
    return 0;
}

运行:

pax$ time myprog
hello
hello
:
hello

real    0m12.861s
user    0m1.762s
sys     0m2.002s

pax$ time ./myprog >/tmp/qq

real    0m0.191s
user    0m0.160s
sys     0m0.050s

换句话说,该环境中的屏幕I / O(XP下的CygWin)持续时间长达67倍,CPU时间长达17倍(可能是因为所有Windows更新)。

答案 1 :(得分:3)

这是另一个快速而有趣的,如果不是科学可靠而且没有经过深思熟虑的测试:

char *memory;
NSLog (@"Start heap allocs");
for (int allocations = 0;  allocations < 100000000;  allocations++)
{
    memory = malloc (1024);
    memory[0] = 1;
    memory[1023] = memory[0] + 1;
    free(memory);
}
NSLog (@"End heap allocs");
NSLog (@"Start stack allocs");
for (int allocations = 0;  allocations < 100000000;  allocations++)
{
    char memory2 [1024];
    memory2[0] = 1;
    memory2[1023] = memory2[0] + 1;
}
NSLog (@"End stack allocs");

和输出:

2011-02-12 11:46:54.078 Veg Met Chilli[4589:207] Start heap allocs
2011-02-12 11:47:06.759 Veg Met Chilli[4589:207] End heap allocs
2011-02-12 11:47:06.759 Veg Met Chilli[4589:207] Start stack allocs
2011-02-12 11:47:07.057 Veg Met Chilli[4589:207] End stack allocs

自己做数学,但这会使堆分配大约长42倍。我必须强调不要引用我的意思,肯定会有瑕疵!最值得注意的是将值实际分配给数据所需的相对时间。

编辑:新的测试数据。

所以现在我只是为每个堆调用一个方法并堆栈,而不是在循环中立即调用它们。结果:

2011-02-12 12:13:42.644 Veg Met Chilli[4678:207] Start heap allocs
2011-02-12 12:13:56.518 Veg Met Chilli[4678:207] End heap allocs
2011-02-12 12:13:56.519 Veg Met Chilli[4678:207] Start stack allocs
2011-02-12 12:13:57.842 Veg Met Chilli[4678:207] End stack allocs

这使得堆的分配只是堆栈分配的10倍。 为了使结果更准确,我还应该有一个没有内存分配的控制方法(但至少做了一些事情,以便不进行优化),并带走那段时间。我接下来会这样做......

编辑:对...... 现在代码看起来像这样:

int control = 0;
NSLog (@"Start heap allocs");
for (int allocations = 0;  allocations < 100000000;  allocations++)
{
    control += [self HeapAlloc];
}
NSLog (@"End heap allocs");
NSLog (@"Start stack allocs");
for (int allocations = 0;  allocations < 100000000;  allocations++)
{
    control += [self StackAlloc];
}
NSLog (@"End stack allocs");
NSLog (@"Start no allocs");
for (int allocations = 0;  allocations < 100000000;  allocations++)
{
    control += [self NoAlloc];
}
NSLog (@"End no allocs");
NSLog (@"%d", control);


-(int) HeapAlloc
{
    int controlCalculation = rand();

    char *memory = malloc (1024);
    memory[0] = 1;
    memory[1023] = memory[0] + 1;
    free(memory);

    return controlCalculation;
}

-(int) StackAlloc
{
    int controlCalculation = rand();

    char memory [1024];
    memory[0] = 1;
    memory[1023] = memory[0] + 1;   

    return controlCalculation;
}

-(int) NoAlloc
{
    int controlCalculation = rand();

    return controlCalculation;
}

结果是:

2011-02-12 12:31:32.676 Veg Met Chilli[4816:207] Start heap allocs
2011-02-12 12:31:47.306 Veg Met Chilli[4816:207] End heap allocs
2011-02-12 12:31:47.306 Veg Met Chilli[4816:207] Start stack allocs
2011-02-12 12:31:49.458 Veg Met Chilli[4816:207] End stack allocs
2011-02-12 12:31:49.459 Veg Met Chilli[4816:207] Start no allocs
2011-02-12 12:31:51.325 Veg Met Chilli[4816:207] End no allocs

所以控制时间是1.866秒。 从分配时间中取出: 堆叠0.286秒 堆12.764秒

因此,堆分配大约需要堆栈分配的45倍。

谢谢你,晚安! :)

答案 2 :(得分:2)

第一点取决于很多事情,真的。如果你的内存不足,那么在堆上分配一些东西可能需要花费几分钟的时间。另一方面,堆栈可能已经在那时分配。

第二点取决于所使用的终端。输出到DOS屏幕是一回事,输出到Windows控制台窗口是另一回事,xterm也与它们完全不同。

至于第3点,我宁愿说它是现代硬盘的另一种方式。他们可以轻松处理每秒钟的megs,你怎么能想象在如此短的时间内输出那么多的终端呢?但是,对于少量数据,您可能是正确的,因为硬盘I / O可能需要一些时间来准备。