您的位置:首页 > 其它

程序性能优化之 内存分配影响

2017-04-28 14:37 183 查看
         本篇不是介绍内存相关知识,如内存分配,布局等, 只是在程序优化性能时,结合案例跟大家分享,期间遇到情况,将知识点,做梳理,便于后续归类和记录,技术水平有限,如果有什么问题,及时给予指正。

        案例一:   程序某模块操作之后, 响应很慢,需要排查和优化性能。

先说明一下排查过程,因为功能比较复杂,所以一般有什么捷径吗?除非这个代码是自己写,否则还针对没有什么捷径,只能通过日志,然后在各个可能点上打日志,然后根据日志分析消耗主要点,然后对其进行分析。

         性能优化难点在于找到主要消耗点, 只能通过时间和经验的累计,由量到质的变化。言归正传,说明具体问题, 排查之后,主要在一个循环中耗时,类似代码如下:

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  );

   }

}

通过以上分析, 大家应该明白问题所在,以及解决, 仅此是程序性能提升不小,尤其针对大量数据,也可以为后续自己的内存申请提供策略。如果有什么不足或者错误,欢迎大家及时给予指正!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: