一 1 在分析一个操作执行太慢,则需要首先分类的是IO操作密集还是cpu计算密集。
这个可以这样区分,用虚拟硬盘工具(例如ramdisk tool)把一部分内存虚拟成硬盘,应用程序和基准文件都安装在虚拟硬盘上,如果程序性能改善明显,则是IO相关的问题。
二 2 针对IO瓶颈的优化:
每次IO操作大约在10ms的量级,100次就是1s左右,所以尽量避免不必要的IO,具体做法有:
预先顺序读文件避免随机访问
合并多个小文件为单个大文件
优化动态库文件的加载
交错IO时间和CPU时间等。
3 正对计算密集的优化
计算密集的性能问题主要有内存分配性能、字符串操作、共享变量的互斥锁保护等,具体优化法有:
去除冗余代码
字符串操作优化
减少内存分配、释放操作,例如用内存池
减少不必要的互斥所操作
根据性能需求选择数据结构
延迟工作、按需执行,例如文档中的图片在翻到哪一页时在加载到内存
减少跨进程调用
用高性能的函数库等
三 1 字节对齐问题(针对不同的平台可能会有差别,而且可能有更改设置)
在全局静态数据区,是按照4个字节对齐的;在堆中,是按照16个字节对齐的。
2 字符串常量存储在全局存储区中,这个区域是在程序编译阶段已分配好的,是程序运行中不可修改的内存区域
char *pLocalString1= " LocalString1 " ; // 指向一个字符长常量
pLocalString[1] = ' a ' ;//试图修改一个不可修改的内存区。
此代码会在运行时导致失败
3 栈上的内存单元,会被自动释放,但是堆上的内存是不会被自动释放的。
int *pnew =new int[5] ;
char *pmalloc = (char *)malloc(1) ;
代码中的pnew和pmalloc是在栈上的,会被自动释放,但是他们指向的内存是在堆上的,需要通过 free() 和 delete 来释放。
此外栈的大小一般有限制(vc上是默认1MB,可以修改),因此下面的代码会运行出错。
int main()
{
char buf [1024*1024];//在栈上声明一个1MB的数组,栈溢出
return 0 ;
}
4 c++中对象,就是内存中的一片区域。
如果一个对象是定义在全局范围内地额变量,则它是存储在全局/静态数据区的;
如果一个对象是通过定义在某个函数内的变量或者实现需要的临时变量来创建时,它是栈上的一个对象。
如果一个对象是通过new 操作符来创建的,它是堆上的一个对象。
需要提醒的是,c++中的作用域是由 { 和 } 定义的,并不是整个函数。
int foo()
{
int nVal = 0;
.................
if( nVal > 0)
{ A a ;//A是一个类
//对象a是在条件语句成立的时候才被创建,在退出条件语句快的时候被销毁
}
p22说明了 通过实现创建对象那个时,一些隐藏的中间临时变量的创建和销毁。
5. 拷贝构造函数的问题
如果类中没有定义拷贝构造函数,那么编译器会产生一个默认的拷贝构造函数。这个默认的拷贝构造函数执行的是位拷贝,即按照找对象的内存空间逐个字节的进行复制。这会带来隐含的内存问题。
#include<stdio.h>
class simpleclass
{
private:
// simpleclass( simpleclass & );
char *buffer;
public:
int nvalue;
simpleclass( int n )
{ nvalue = n;
buffer = new char[n] ; };
~simpleclass()
{
if(buffer){ delete buffer ; }
};
};
int main()
{
simpleclass a(10);
simpleclass b=a;
return 0;
}
这个程序中,因为使用默认的拷贝构造函数,造成a和b的buffer指向同一个内存区,析构时,两次释放,造成程序崩溃。