很多时候性能问题都不是来自语言本身,编译器,网络或者IO的。凭猜想是很难得到答案的。需要用
profile性能分析工具来定位问题。
很多时候是来自系统的内存开销和CPU计算导致的性能问题。
性能问题100%来自于自己项目的代码,
百分之10-20%的代码消耗掉了80-90%的性能。
思想方法一:lazy evaluation(懒惰计算法)-当系统CPU内存紧张时候
方法:减少避开延迟计算,真正需要时候才计算需要的;内存对象要控制好,CPU控制好,IO控制好。
不管是内存占用还是表达式算法运算,能不计算尽量不计算,需要的时候才计算。
1.内存方面考虑-避免内存中频繁的申请对象和释放对象,同时避免大型对象的每次都初始化所有数据
C++的面向对象特性使得内存里面有很多的对象,类似C语言如果频繁的分配了很多内存给结构体又释放结构体那么同样会导致内存性能问题。
2.CPU方面,如果遍历的数量比较多,当时当前不需要这么大的范围或者很多是空的,那么缩小遍历范围。当前还不需要的拷贝或者运算可以当需要的时候才进行运算。
3.IO方面,一开始就浪费很多IO去读取数据,但是你并不需要的,那么需要的时候才去取数据。或者采用延迟加载机制。
思想方法二:over-eager evaluation
(过度热情计算法)-当该计算比较频繁且下一步很很可能再计算时候
方法:用内存缓存空间换时间,用数量换时间;系统调用比进程间函数耗时很大那么申请更大块的内存,从计算的紧密相关性将CPU计算结果缓存起来,将IO读取更大块的内容缓存起来。
STL容器vector动态增加一倍,是为了避免系统调用比进程间函数耗时,很大那么申请更大块的内存。
跟踪运行时的最小值、最大值和平均值,这需要额外的空间,但是能节省时间。
Cache运算结果需要更多的内存,但是一旦需要被缓存的结果时就能减少需要重新生成的时间。Prefetch需要空间放置被prefetch的东西,但是它减少了访问它们所需的时间。
STL
自从有了计算机就有这样的描述:你能以空间换时间。(然而不总是这样,使用大型对象意味着不适合虚拟内存或cache页。在一些罕见的情况下,建立大对象会降低软件的性能,因为分页操作的增加(详见操作系统中内存管理 译者注),cache命中率降低,或者两者都同时发生。如何发现你正遭遇这样的问题呢?你必须profile, profile, profile。
C++数据成员对象的构造和析构很难避免最多用对象指针需要时候才构造。C++的局部对象也可以尽量少的调用。
关键是C++函数参数传入和函数返回值之间产生的临时对象,这些临时对象的无意间构造和析构会比较浪费时间,特别是大对象的时候。
传入参数时候,尽量用引用或者指针类型,能用常量引用常量指针的尽量使用(非类型转换的常量引用不会产生临时对象,看下面测试代码);当类型不匹配时候C++编译器会因类型转换产生临时对象,传值类型和传常量引用类型会产生临时对象,传非常量引用不会产生临时对象但是编译不过(不会产生临时对象是因为程序员意图是改变参数外部的值,而如果产生了就改变的时候临时对象的值,反证法证之)。
函数返回值时候,能返回指针的尽量返回指针;返回引用通常是在操作符重载函数返回自身时候,如果是类函数成员那么返回引用不如什么都不返回用Calculate函数代替说明次序关系;有返回对象的无法代替那么也必须返回对象,特别返回指针很危险时候就应该返回一个对象。
// 非类型转换的常量引用不会产生临时对象 测试代码
class A
{
public:
void SetNum(int num)
{
m_nNum = num;
}
void Display()
{
cout<<"m_nNum value:"<<m_nNum<<endl;
}
A& operator +(const A &bObj)
{
this->m_nNum += bObj.m_nNum;
return (*this);
}
A& operator =(const A &a)
{
this->m_nNum = a.m_nNum;
return (*this);
}
private:
int m_nNum;
};
int main()
{
A aInstance;
aInstance.SetNum(10);
A bInstance;
bInstance.SetNum(10);
aInstance = aInstance + bInstance;
aInstance.Display();
}
输出值:
+ aInstance {m_nNum=10 } A
+ &aInstance 0x0016f768 {m_nNum=10 } A *
+ bInstance {m_nNum=10 } A
+ &bInstance 0x0016f75c {m_nNum=10 } A *
+ bObj {m_nNum=10 } const A &
+ &bObj 0x0016f75c {m_nNum=10 } const A *
+ this 0x0016f768 {m_nNum=20 } A * const
+ *this {m_nNum=20 } A
参考资料:
<<More Effective C++>>
参考资料:
<<More Effective C++>>