`

缓存的力量,windows下的slub分配器

阅读更多

上张图先:

该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.在分配次数差不多的情况下,对象体积大的速度反而比小的快了很多。不得其解。后来和同事一致认为,就好比读取int i; char c,后者耗费的时间肯定比前者多一个指令

 

3.同样是2k的对象大小,在内存从32->128的情况下,系统的耗时差了10倍,我的差了4倍。进一步说明在大内存下,缓存不连续下的性能最大耗费

 

4.在128MB,我没有测试1k(太慢了)。但是我敢肯定跟32mb的差值远远小于2k的10倍。很简单原理如下:在系统进行分配内存时,都会或多或少的加入一些字段进行校验或者记录信息。如果你的大小是2K,那么对齐后的大小必然是>2k,如果系统的页面颗粒不进行调整,就会造成极大的浪费。所以你的对象分配时在32机器上跟4KB的页面对齐有问题,就要小心了。

 

多线程下:

5.尝试了下开多核的缓存设置(实现见代码,很简单的技巧)。在单线程下,反而显得慢。这个道理很简单,单个线程的忙碌,切到另外个CPU非常偶然。比如10次的0号CPU,1次的1号CPU。切的缓存命中不大,反而还要0号再次反切。在多线程下虽然有提升,但是少得可怜。由于硬件条件,没有再进行4核,8核的测试。





两个额外的想法:

1.C的链表 VS STL

先来推一个论点:
STL中只是对链表对象的一个包装,因为对用户是透明的,所以给用户展示的还是原来的结构。那么就意味着,链表信息无法原来的结构体中取得,如果要进行增,删,改,则必须进行查询找到链表节点

假设有结构
struct page
{

list head; //如果是C,
以linux下的链表使用方法为代表,直接将信息作为结构体的一个成员变量
};

接着将page串成链表
C中,list_add_tail(). C中是以数据结构和操作方法分开,典型的过程式写法
C++中,list<page*> List; List.push(); 类的思维写法,一个对象包括代码和数据

当我要进行删除的时候
void *p; //我的内存地址
pPage = virt_to_head_page(p); //反算出page
C中,list_del(pPage);//直接删除,因为本身就有结点信息
C++中,List.删除(pPage); //我的做法是,先find到itr,然后erase.如果是remove,好象是一个遍历



2. 执行序列的优化

int i = 40;
int j = 100;
i = 20;
j = i;
i = 30;

那么在执行j=i的时候,能不能探测到下一条语句是i,可以事先缓存住i的地址,然后就可以直接执行i=30这条语句.那么在INTEL CPU中使用的技术是乱序。但找了几天资料也没搞明白怎么防止不乱序(即j=i先于i=30执行)。这样的话就可以衍生到
应用层对象处理上优化。比如有1,10, 2玩家发来指令,先放在指令池里(cpu架构也是这么干的)但是可知1,2号在同一个页上,于是就可以先处理1,2玩家的命令。









 

2
3
分享到:
评论
1 楼 lin_style 2010-07-14  
草。居然还有SB踩我。留下意见来

相关推荐

    Linux Slub Allocator工作原理

    - **局部缓存(per-CPU slab cache)**:为了进一步提高性能,Slub分配器还为每个CPU维护了一个局部缓存,其中包含了部分slab缓存。这样,在同一CPU上进行内存分配时,可以优先使用局部缓存中的对象,避免了锁的竞争...

    SLub算法分析

    3. **缓存填充**:如果缓存为空,SLUB会尝试从空闲页(页面分配器)获取新的物理页,然后将这些页面转换为slabs。 4. **对象初始化**:新分配的页面会被切分为多个对象,并将每个对象设置为已初始化状态,准备分配。...

    linux slob slab slub allocator

    SLUB分配器的设计理念是简单易懂,最小化指令成本,并且注重调试能力以及执行时间的友好性。SLUB相较于SLAB,取消了队列,简化了slab结构,并且提高了处理器缓存利用率,降低了锁的争用。SLUB的一个显著特点是其优秀...

    slabdbg:GDB插件,有助于利用Linux内核的SLUB分配器

    GDB插件使开发针对SLUB分配器Linux内核漏洞更加容易。 它显示slab缓存的内容,并允许在分配/释放操作上设置断点。 安装 无需安装,只需键入source slabdbg.py就足以让您入门。 用法 Usage: slab list - Display ...

    slaballocators.pdf

    本文将基于“slaballocators.pdf”这一资料,深入探讨 slab 分配器的基本概念、不同类型的 slab 分配器(SLAB、SLOB 和 SLUB)以及它们的发展历程。 #### 二、Slab 分配器的角色 在 Linux 内核中,内存管理是非常...

    linux内核源代码分析,自己写的

    内核的物理内存管理主要依赖于伙伴系统和slab/slob/slub分配器。伙伴系统是基础,它按照页来管理内存,用于分配和释放多页大小的内存块。伙伴系统将空闲内存块链接在一起,形成一个空闲链,当需要分配内存时,会找到...

    linux内存管理学习文档.doc

    在Linux系统中,内存管理包括了多种机制和数据结构,如slub内存分配器、页(frame)管理、缓存(kmem_cache)等。以下是对这些关键知识点的详细说明: 1. 常见结构体 - `struct kmem_cache`: 这个结构体是Linux内核中...

    Linux内核04.pptx

    总结来说,Linux内核内存分配器是一个复杂而精细的系统,它通过内存池、位图、链表以及专门的分配器如Slab、Slub和Slob,确保了内核内存的高效、低碎片和安全分配。了解这些概念对于理解和优化Linux内核的性能至关...

    Linux内核Slab内存缓冲区管理器.pdf

    此外,Slab管理器还支持多级缓存(slab、slub和slob),以适应不同的性能和资源需求。 总的来说,Slab内存缓冲区管理器是Linux内核内存管理的关键组成部分,它通过精细化的内存分配策略和对象复用,显著提升了内核...

    008.利用堆大小差一错误爆破Linux内核-008.CVE-2016-6187 Exploiting Linux kernel

    首先,我们需要了解SLUB分配器的基本概念。SLUB是Linux内核中的一种高效内存分配器,用于管理内核空间中的动态内存分配。它预先分配相同尺寸的对象,存储在称为slab的内存块中。每个slab包含多个对象,且每个对象在...

    Linux内存管理详解

    SLAB、SLUB和SLOB都是缓存分配器,它们维护了一个内存池,其中包含预分配且已初始化的对象,以满足频繁创建和销毁小对象的需求。这些分配器可以高效地管理小块内存,避免了传统内存分配时的开销。 Linux内存管理的...

    12.docx Memory Management

    因此,内核内存分配器必须具备高度的健壮性,能够及时处理错误并确保系统稳定运行。 在Linux内核中,物理内存被组织成称为“页面”(Pages)的基本单位。页面大小是由特定架构定义的,常见的有4KB或8KB。这种划分...

    Linux memory manage

    内存管理的层次结构图展示了不同级别的内存分配策略,如kmalloc处理小内存分配,slab分配器在内核层面提供缓存对象的分配,而vmalloc则用于大内存的非连续分配。`do_page_fault`函数是处理缺页异常的关键,当进程...

    Linux内存管理详解.ppt

    slab分配器在Linux 2.4.22之后被引入,优化了小对象的内存分配,而slub是2.6.22版本引入的slab分配器的简化版本。同时,页表管理和TLB刷新也是内存管理的重要环节,确保了虚拟地址到物理地址的正确映射。 总的来说...

    Chapter2.docx

    SLAB 分配器将大块内存分割成小的、固定大小的对象缓存,每个缓存称为一个 slab。SLUB 是 SLAB 的简化版本,它省略了某些 SLAB 中的元数据,以减少内存开销和提高性能。 总的来说,Linux 内核通过 NUMA 架构、页表...

    Linux内存管理详解学习教案.pptx

    Linux内存管理的层次结构复杂,从页表管理到缺页异常处理,涉及多层调用,如do_page_fault处理缺页异常,通过kmem_cache_create和kmem_cache_alloc进行缓存分配,以及通过kmalloc、slab分配器等进行内存分配。...

    Linux内存管理详解PPT学习教案.pptx

    此外,SLAB、SLUB和SLOB分配器进一步优化了内存分配,允许在一个页面内独立分配多个小块内存,有效减少了内部碎片。 内存管理层次关系图展示了从用户空间到内核空间的内存分配流程,包括kmalloc、slab分配器、页表...

    终极内存技术

    因此,理解并使用更高效的内存分配器,如jemalloc或tcmalloc,可以显著提高内存分配效率。 缓存是提升性能的重要手段,Linux内核提供了多种缓存机制,如Page Cache、SLAB和SLUB等。理解这些缓存的工作原理,以及...

    深入理解LINUX内存管理学习笔记

    - 包括伙伴系统(buddy system)和slub/slab分配器,用于高效地分配和回收小块内存。 9. **高速缓存(Cache)**: - Linux内存管理中,缓存机制提高了I/O性能,如page cache和dentry cache等。 10. **内存泄漏...

    Linux 2.6存储管理子系统新特性分析.pdf

    - SLAB分配器被用于管理内核对象的内存分配,2.6内核引入了SLUB,这是一种更轻量级的版本,减少了元数据开销,提高了小对象分配的性能。SLUB允许更快的分配和回收,同时保持内存利用率的高效率。 3. **内存压缩** ...

Global site tag (gtag.js) - Google Analytics