C++性能的编程技术

一.影响C++性能的基本原理:

1.       I/O的开销是最昂贵的

2.       函数调用的开销是一个因素,因此我们应该内联短小,频繁调用的函数

3.       复制对象的开销是昂贵的。最好选择按引用传递,而不是值传递。

4.       最好采用栈内创建对象,而不是采用堆创建对象 一般在堆内创建对象是在栈内创建对象花费的时间是20备左右。

5.       理解每种操作的代价。

二.临时对象:

产生临时对象一般来说有如下两种场合。

(1)   当实际调用函数时传入的参数与函数定义中声明的变量类型不匹配。

(2)   按值传递

(3)   当函数返回一个对象时

class Rational

{

         Public Rationalint a=0int = 1):m(1),n(b){}

Private:

    Int m;

    Int n; 

}

Rational  r1(100);

Rational  r2= Rational(100);

Rational  r2=100;  //两次构造和一次析构

优化方式:

1.       传值和传引用

2.       返回引用

3.       构造函数申明为explicit并重载+-=之类的运算符。 

三.内联:

函数调用的开销:

Void foo()

{

           I=func(a,b,c);

}

调用者(这里是foo)在调用前需要执行如下操作。

1)参数压栈:这里是abc。压栈时一般都是按照逆序,因此是c->b->c。如果abc有对象,则需要先进行拷贝构造。

2)保存返回地址:即函数调用结束返回后接着执行的语句的地址,这里是处语句的地址。

3)保存维护foo函数栈帧信息的寄存器内容:如SP(堆栈指针)和FP(栈帧指针)等。到底保存哪些寄存器与平台相关,但是每个平台肯定都会有对应的寄存器。

4)保存一些通用寄存器的内容:因为有些通用寄存器会被所有函数用到,所以在foo调用func之前,这些寄存器可能已经放置了对foo有用的信息。这些寄存器在进入func函数体内执行时可能会被func用到,从而被覆写。因此foo在调用func前保存一份这些通用寄存器的内容,这样在func返回后可以恢复它们。

接着调用func函数,它首先通过移动栈指针来分配所有在其内部声明的局部变量所需的空间,然后执行其函数体内的代码等。

最后当func执行完毕,函数返回时,foo函数还需要执行如下善后处理。

1)恢复通用寄存器的值。

2)恢复保存foo函数栈帧信息的那些寄存器的值。

3)通过移动栈指针,销毁func函数的栈帧,

4)将保存的返回地址出栈,并赋给IP寄存器。

5)通过移动栈指针,回收传给func函数的参数所占用的空间。

缺点:增大代码编译后长度

对于小型的,频繁调用的函数,而对于很长的函数基本上不适用

四.内存池

new/deletemalloc/free在堆上分配和释放内存的开销:

1.在堆上分配内存有额外开销。

 

2.造成内存碎片,影响系统性能。

应用实例:linux slab分配器,apache内存池

设计考虑固定大小还是变长,单线程还是多线程。六.缓存

  更新策略FIFO LRU  LFU

  Memcache

五.理解STL的应用场合

Vector 动态数组,内存空间是连续的

List   双向;列表

Multiset 按序排列的容器,内部采用红黑树

 

数组

Vector

list

Multiset

原因

后端插入

70ms

250ms

930ms

6500ms

Vector动态增长时所带来的开销

List指针所带来的开销

后端删除

 

60ms

750ms

 

List指针操作所带来的开销

前端删除

 

700ms

7ms

 

复制所带来的开销

遍历(

110ms

110ms

2600ms

 

局部性原理指针访问的开销

查找

40ms

40ms

800ms

0.06ms

List程序局部性原理指针访问的开销

Multiset 红黑树高效查找

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值