C++ 性能剖析 (三):Heap Object对比 Stack (auto) Object

通常认为,性能的改进是90 ~ 10 规则, 即10%的代码要对90%的性能问题负责。做过大型软件工程的程序员一般都知道这个概念。

然而对于软件工程师来说,有些性能问题是不可原谅的,无论它们属于10%或是90%,都是“必须”改进的。这里就讲讲其中的一个问题:用heap还是用stack的问题。

Java, C#,和JavaScript的程序员一般都不用管自己创建的object是在heap里还是在stack里,因为对于这些语言,object 只能“生活在”heap里。这无疑对于程序员来说简单了许多。但是对于C++程序员来说,你可以选择三处来创建object:

  • 程序的data section
  • 工作堆栈
  • Heap

Object 因该生活在哪里?这个问题必须由应用的属性来决定,有时是没有选择的,比如对于动态产生的全程变量,只有活在heap里,别无它途。

然而,一旦我们有选择,比如临时的,作为复杂数据的载体的object,答案是清楚的:应该首选stack. 比如下面简单的例子:

 

          // heap vs stack test

       double HeapVsStack(bool heap, int loop, int &result)

       {

             if (heap)

             {

                    clock_t begin = clock();

                    for(int i = 0; i < loop; ++i)

                    {

                                        intPair *p = new intPair(1,2);

                                        result += p->ip1 + p->ip2;

                                        delete p;

                    }

                    clock_t end = clock();

                    return double(end - begin) / CLOCKS_PER_SEC;  

             }

             else

             {

                    clock_t begin = clock();

                    for(int i = 0; i < loop; ++i)

                    {

                                        intPair p = intPair(1,2);

                                        result += p.ip1 + p.ip2;

                    }

                    clock_t end = clock();

                    return double(end - begin) / CLOCKS_PER_SEC;  

             }

       }

 

程序中黑体放大的部分是要测量的“应用逻辑”,上方在heap中创建了一个intPair,用完后delete掉。下方在stack里定义一个同样的auto变量,用完后无须care.

对这个程序作下列简单测试调用:

int result = 0;

printf("Heap time: %f \n", HeapVsStack(true, 100000, result));

printf("Stack time: %f \n", HeapVsStack(false, 100000, result));

 

我不得不调用100000次,原因是它们的耗时差别实在太大了:stack 的用例不到10000次以上都显示0ms.

测试结果,heap用了300ms, stack用了5ms, 相差60倍。

结论:

1) 如果应用逻辑容许,用 stack-based auto 变量,千万不用 heap 变量.

2) 如果需要大量用heap,建议用std::vector来当作自己的 heap 简单管理器用。避免直接地,大量地用heap来创建 ad-hoc  object.

3) 有些临时计算用的class可以考虑禁止在heap中生成,见http://stackoverflow.com/questions/1941517/explicitly-disallow-heap-allocation-in-c 文章。

 

2014-8-23 西雅图

posted @ 2014-08-24 04:24  Yang_Lian  阅读(1151)  评论(0编辑  收藏  举报