日期:2014-05-17 浏览次数:20694 次
上张图先:
该CPU L2=3MB
首先谈谈对象分配池.不管是内存池也好,对象池也好,首要的速度就是要快。可能有人说内存池为了碎片问题,那减轻碎片负担是不是也是为了速度快呢? 影响速度首先要从2个角度考虑,一个是机器的硬件特性,其次是缓存的命中率。硬件特性包括了对各种不同大小字段的读取,而缓存命中率在大内存的时候更显得犹为重要(因为内存没有硬盘的I/O瓶颈一说)。一会会结合数据图一一指出。所以在写的时候,为slub提供了以下特性:(多参考自linux源码,精练而成)
1.以页面为颗粒度,进行分配。
比如32机器上的页面为4KB,则每次分配以4KB做为颗粒度。当然这个可以调节,以支持大于一个页面的对象。
2.尽量从回收的页面中分配,以保持缓存命中率。并且维持这种顺序,不被分配打乱
比如一个页面分为100个对象,释放了10个对象,那么下次分配时,尽量从释放的10个中申请。而常见的链表式池,在使用次数多后,最影响的性能方面就是1号对象指向了最末尾等等
3.缓存的回收
虽然在服务器上内存的政策是鸵鸟式,这也是我以前的观点。但是现在的想法还是如果能做到一款动态伸缩,并且不影响效率,实在是快哉。不过在该代码里面,回收暂时不是重点,在回收的时候我也仅仅以vector遍历查找。一般不开
4.坏区的检测
对每个内存块分配特定的值,检测是否坏,或者不对的内存.可以屏蔽
5.多核的缓存支持
这里多核不是指多线程的支持。当然,它支持多线程并发。这里指的是利用多核建立的缓存结构。写之前对它将信将疑,不知道性能能提高多少,测试后也确实如此,性能提高得可怜。但也可能鉴于机器情况(双核),如果在忙碌的多核下,我相信性能还是有多提升的。
分析数据得出来的经验:
补充下测试环境,图里没写全:windows xp sp2+32位CPU
测试的时候, 网页等操作正常,myslub中所有检测全关
没有测试所有的数据,一是平常中已经测过,但没有记录,发上来总得象样点;二是心里大概有个样本了,没有花费太多时间做这事
我的测试方式:
?
?
S32 __CMYMalloc::Run()
{
DWORD t1 = GetTickCount();
while(g_bQuit==false && InterlockedDecrement(&m_nCount)+1 )
{
int i, nRand;
//申请
nRand = Random(0, name_viralloc::SUM_ALLOC_BYTE/m_nObjectSize-Vector.size());
for(i=0; i<nRand; ++i)
{
void *p = m_Kmem.KmemMalloc();
if(NULL==p)
{
break;
}
*(int*)p = 1000;
Vector.push_back(p);
++m_nMalloc;
}
//释放
nRand = Random(0, Vector.size());
for(i=0; i<nRand; ++i)
{
int j = Random(0, Vector.size());
if( NULL==Vector[j] )
{
continue;
}
m_Kmem.KmemFree(Vector[j]);
Vector.erase(Vector.begin()+j);
++m_nFree;
}
}
printf("spend:%d\n", GetTickCount()-t1);
return 0;
Vector,事先进行了reserve,?name_viralloc::SUM_ALLOC_BYTE/m_nObjectSize计算出能分配的所有对象数。也就是说,一个单位的测试
动作包括了,随机分配内存,再计算出一个随机释放内存的数,并且对每个释放的索引再次随机。那么进行几次这样的单位测试成为一个很重要的指数。理想的值应该是跟能分配的所有对象数进行一个比例进行,我在测试中一般设为500-1000,并且以KB为单位。(如果是byte为单位,速度慢得重启,十几,二十分钟的计算)虽然有点偏颇,但还是可以做为一个样本参考。
总结出的一些内存经验:
单线程:
1.一次性分配2个页面做为一个单位颗粒,可以提高速度吗?证明不能,甚至还有拖慢的嫌疑。在32位机器下
2.在分配次数差不多的情况下,对象体积大的速度反而比小的快了很多。不得其解。后来和同事一致认为,就好比读