本篇不是介绍内存相关知识,如内存分配,布局等, 只是在程序优化性能时,结合案例跟大家分享,期间遇到情况,将知识点,做梳理,便于后续归类和记录,技术水平有限,如果有什么问题,及时给予指正。
案例一: 程序某模块操作之后, 响应很慢,需要排查和优化性能。
先说明一下排查过程,因为功能比较复杂,所以一般有什么捷径吗?除非这个代码是自己写,否则还针对没有什么捷径,只能通过日志,然后在各个可能点上打日志,然后根据日志分析消耗主要点,然后对其进行分析。
性能优化难点在于找到主要消耗点, 只能通过时间和经验的累计,由量到质的变化。言归正传,说明具体问题, 排查之后,主要在一个循环中耗时,类似代码如下:
CString strInfor;
clock_t sTime, eTime;
sTime = clock();
int nSize = m_vecData.Size();
for(int nInd=0; nInd<nSize ; ++nInd)
{
strInfor = strInfor + _T("&"), + m_vecData.at(nInd);
}
eTime= clock();
double dbGap = (eTime - sTime) /CLOCKS_PER_SEC;
以上代码片段,也没有其他逻辑, 简单一个字符拼接,在size=10000时,会消耗将近2秒左右时间,如果size=50000时居然耗时24描述, 以上数据为debug模式下测试
针对如上问题排查: strInfor = strInfor + _T("&"), + m_vecData.at(nInd); 这个行代码,弄清到底做了写什么东东,导致这么旧:
排查之后,上述代码主要做了如下几件事情:两次+操作,一次=操作, 跟踪代码之后,;
一次+操作经历如下步骤:
1, 先计算+之后大小,然后申请内存;
2, 底层两次memmove操作将值拷贝的新的内存中;
一次=操作会经历如下:
1,+新生成的值复制给予受托人Infor;
2, 针对之前的做一次Free释放操作;
具体的代码,大家可以单步调试中去跟踪, 经过分析,频繁的内存申请,释放比较耗时耗力,必然消耗性能,看来一定要正视每一个接口背后的实现逻辑,否则有可能怎么影响性能都不晓得。
根据以上的排查和cstring的接口,选如下实现替代:
CString strInfor;
clock_t sTime, eTime;
sTime = clock();
int nSize = m_vecData.Size();
for(int nInd=0; nInd<nSize ; ++nInd)
{
strInfor.Append(_T("&"));
strInfor.Append(m_vecData.at(nInd));
}
eTime= clock();
先测试性能:同样的条件10000是,计划不耗时,职位0毫秒(140-140),50000万时,几乎耗时为0描述, (165-124);可见对性能的影响,根据调试发现其主要过程如下:
1,一次根据大小策略,分配内存操作;
2,一次memmove操作将值拷贝的新的内存中;
其主要性能差异主要在接口中,针对分配算法的策略情况,具体代码如下:
PXSTR PerpareWrite(int nLenght)
{
CStringData* pOldData = GetData();
int nShared = 1- pOldData->nRefs;
int nTooShort = pOldData->nAllocLenght -nLenght;
if(nShared |nTooShort )
{
PerpareWrite2(nLenght);
}
}
核心算法
void PerpareWrite(int nLenght)
{
CStringData* pOldData = GetData();
if(pOldData ->nDataLenght>nLenght)
{
nLenght = pOldData ->nDataLenght;
}
if(pOldData->IsShared())
{
Fork(nLenght ); ///里面只是根据大家申请内存,没做任何策略
}
else if(pOldData ->nAllocLenght <nLenght))
{
如下策略,是否大家在那里见过, vector是动态数据,其中针对内存做预留处理,避免多次申请
int nNewLenght = pOldData ->nAllocLenght ;
if(nNewLenght >1024)
{
nNewLenght += 1024;
}
else
{
nNewLenght *=2;
}
if(nNewLenght <nLenght)
{
nNewLenght = nLenght;
}
Reallocate(nNewLenght );
}
}