C++ 应用程序性能优化

C++ 应用程序性能优化

C++ 应用程序性能优化

eryar@163.comhtml

1. Introduction程序员

对于几何造型内核OpenCASCADE,因为会涉及到大量的数值算法,如矩阵相关计算,微积分,Newton迭代法解方程,以及非线性优化的一些算法,如BFGS,FRPR,PSO等等用于多元函数的极值求解,因此这些数值算法的性能直接影响系统的性能。软件的性能优化是计算机软件开发过程当中须要一直关注的重要因素,所以有必要学习下C++应用程序性能优化的方法。算法

在网上寻找相关资料时,发现这方面的资料也不多,最后发现一本由电子工业出版社出版的《C++应用程序性能优化方法》,从中能够学习下IBM的性能优化方法。性能优化

本文主要结合《C++性能优化方法》并结合代码实例来讲明内存优化处理对程序性能的影响。看完本书,其实发现C++性能优化方法主要仍是依赖的计算机相关的基础知识,好比说计算机操做系统,数据结构与算法等等。数据结构

2.Memory Optimize多线程

C++程序中的存储空间能够分为静态/全局存储区,栈区和堆区。静态/全局存储区和栈区的大小通常在程序编译阶段决定;而堆区则随着程序的运行而动态变化,每一次程序运行都会有不一样的行为。这种动态的内存管理对于一个程序在运行过程当中占用的内存大小及程序的性能有很是重要的影响。函数

由于静态/全局存储区在编译时就已经肯定了,而栈区则是由操做系统在管理,这些都不劳程序员费神。就是这个堆区是提供给程序员的自由舞台,能够任性发挥。堆区的存储区域怎么玩呢?理解了这三个问题应该就知道了:一是堆区数据怎么产生(从哪儿来)?二是堆区的数据怎么销毁(到哪儿去)?堆区数据怎么访问?由C++标准规定得知,C++实现经过全局的new和delete来提供动态内存的访问和管理。而堆区数据的访问就是经过指针了。当使用new/delete来操做堆上的存储区域时,操做系统就要对堆的存储区域进行管理,因此这个管理工做就会对应用程序的性能有影响。工具

为了解决内存泄露问题,即new以后再也不使用时并无delete,OpenCASCADE中入了Handle智能指针的宏定义。Handle的使用也很简单,只须要将用Handle(Class)就能够了。post

利用默认的内存管理new/delete在堆上分配和释放内存会有一些额外的开销。系统在接收到必定大小内存请求时,首先查找内部维护的内存空闲块表,而且须要根据必定的算法(例如分配最早找到的不小于申请大小的内存块给请求者,或者分配最适于申请大小的内存块等)找到合适大小的内存块。若是该空闲内存块过大,还须要切割成已分配的部分和较小的空闲块,而后系统更新内存块表,完成一次内存分配。相似地,在释放内存时,系统把释放的内存块从新加入到空闲内存块表中。若是有可能的话,能够把相邻的空闲块合并成较大的空闲块。性能

默认的内存管理函数还考虑到多线程的应用,须要在每次分配和释放内存时加锁,一样增长开销。可见,若是应用程序频繁地在堆上分配格释放内存,则会致使性能的损失。而且会使系统中出现大量的内存碎片,下降内存的利用率。

因而可知,在简单的new和delete背后,系统默默地为咱们作了这么多的事,而作这些事都是要花时间的啊!虽然默认的内存管理算法也考虑了性能,可是考虑的是更通用的状况,为了应付更复杂、更普遍的状况,须要作更多额外工做。而对于具体的应用程序来讲,适合自身特定的内存管理则能够得到更好的性能,为此OpenCASCADE引入了本身的内存管理机制,与内存池概念相似。OCCT的内存经过配置,可使用没的优化技术,或者不使用任何优化直接使用系统的malloc和free。这些配置都是经过环境变量来实现,其中打开和关闭内存优化的开关是环境变量:MMGT_OPT,这个默认是0,即不使用任何优化;设置成1就是使用;设置成2就是使用TBB的内存优化技术(这个的前提是第三方库正确配置,若是没有仍是使用的malloc和free;

复制代码
// paralleling with Intel TBB
#ifdef HAVE_TBB
  #include <tbb/scalable_allocator.h>
  using namespace tbb;
#else
  #define scalable_malloc malloc
  #define scalable_calloc calloc
  #define scalable_realloc realloc
  #define scalable_free free
#endif
复制代码

 

下面经过代码来看看使用内存管理的性能有什么变化。

3.Code Example

下面经过程序来看看使用这些技术对性能的影响:

复制代码
/*
*    Copyright (c) 2016 Shing Liu All Rights Reserved.
*
*           File : main.cpp
*         Author : Shing Liu(eryar@163.com)
*           Date : 2016-07-31  11:54 
*        Version : OpenCASCADE7.0.0
*
*    Description : Test OCCT Memory Manager and Handle(smart pointer).
*/

#include <OSD_Timer.hxx>

#include <Poly.hxx>
#include <Poly_Triangulation.hxx>

#pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")

/*
 *@brief test memory without Handle(smart pointer) management.
 *
 */
void testMemory(Standard_Integer theCount)
{
    OSD_Timer aTimer;
    aTimer.Start();

    for (Standard_Integer i = 0; i < theCount; i++)
    {
        Poly_Triangulation* aTriangulation = new Poly_Triangulation(10, 5, Standard_False);

        delete aTriangulation;
    }

    aTimer.Stop();
    aTimer.Show();
}

/*
*@brief test memory with Handle(smart pointer) management.
*
*/
void testHandle(Standard_Integer theCount)
{
    OSD_Timer aTimer;
    aTimer.Start();

    for (Standard_Integer i = 0; i < theCount; i++)
    {
        Handle(Poly_Triangulation) aTriangulation = new Poly_Triangulation(10, 5, Standard_False);
    }

    aTimer.Stop();
    aTimer.Show();
}

/*
 * @brief set environment variable MMGT_OPT=0 to use malloc/free directly;
 *        set environment varialbe MMGT_OPT=1 to use OCCT memory optimization technique;
 *        set environment variable MMGT_OPT=2 to use paralleling with Interl TBB;
 */
int main(int argc, char* argv[])
{
    int aCount = 100000;

    std::cout << "\ntest pointer without handle" << std::endl;
    testMemory(aCount);

    std::cout << "\ntest pointer with handle" << std::endl;
    testHandle(aCount);

    return 0;
}
复制代码

若是直接运行上面的代码编译的程序,获得的结果以下图所示:

wpsECE0.tmp

由图可知,当使用Handle(智能指针)的时候,时间上影响不大,即便用Handle对性能影响基本上能够忽略,可是获得不少好处,主要的就是不用本身去delete了。使用Visual Studio的性能分析工具查看,结果也相似:

wpsECF1.tmp

时间的开销也是集中在内存的分配上面:

wpsED02.tmp

注意到上面的Allocate()是类Standard_MMgrRaw的,便是直接使用的系统的malloc和free来管理内存。下面设置环境变量MMGT_OPT=1来使用OCCT的内存优化类看看对性能影响如何?

wpsED03.tmp

程序运行的结果以下图所示:

wpsED13.tmp

与没有使用内存优化的时候0.1相比,使用了内存优化处理的要快40%左右。

由下图能够看出,性能热点也是集中在内存的分配上面:

wpsED14.tmp

注意如今内存分配使用的是Standard_MMgrOpt类中的Allocate函数:

wpsED15.tmp

总的来讲,将环境变量MMGT_OPT设置成1来使用OCCT的内存优化算法,性能提高仍是很明显的。

4.Conclusion

当程序规模愈来愈大,算法越来算复杂的时候,找到性能的瓶颈越麻烦一些。性能优化第一步是测量,找到合适的测量工具。《C++应用程序性能优化》一书中提供的是IBM Rational Quantify,在网上搜了下还有Intel VTune Amplifier等,功能都很强大。在Windows中开发程序使用的Visual Studio自带了性能分析功能,使用起来也比较方便。

找到性能瓶颈,就要对其进行分析缘由,进而修改程序,提升性能。这方面的方法论能够借鉴《C++应用程序性能优化》,从数据结构、程序启动、内存管理等方面来分析。摘出此书中程序性能优化的流程图:

wpsED16.tmp

5. References

1.冯宏华,徐莹,程远,汪磊. C++应用程序性能优化. 电子工业出版社.

2.Scott Meryers. Effective C++(评注版). 电子工业出版社. 2011

3.OpenCASCADE Foundation Classes Document 7.0.0. 2016

相关文章
相关标签/搜索