五千年(敝帚自珍)

主题:【请教】自建memory pool,请问如何管理内存碎片 -- 东方射日

共:💬6 🌺2 新:
全看树展主题 · 分页首页 上页
/ 1
下页 末页
家园 【请教】自建memory pool,请问如何管理内存碎片

我们知道系统提供的动态内存分配new-delete; malloc-free,系统会完成内存碎片的整理。

自建的memory pool就要自己进行了。

memory pool重载new,delete,从自建的memory pool中动态分配内存。有可能产生内存碎片

例如new-delete产生了4个50k的fragment,共有200k的free memory,此时allocate 100k的内存会失败

什么算法处理?

我的想法是建立链表,存储pool中的偏移量,size和应用中申请内存的指针的指针。线程idle时进行内存整理,DEFRAGMENT会涉及内存块的移动,就要修改应用中的pointer。 defragment后通过指针的指针修改应用中指针的指向。

问题是重载new,应用中不会传递给我他申请内存的指针:

调用重载new,

void * p =new(size);

我在new中返回一个指针指向pool中。

但是我不知道void **p,无法在链表中存储*p的地址。整理内存时,无法修改应用中的*p的值

我想除非改变new的形式:new(size, **p),但显然不是一个好主意。

诸大侠有什么建议??

家园 请管理员将主贴移信息技术版,再删除该信息
家园 这个思路好像不太对

如果分配内存后,获得的handle又赋值给另一个指针,岂不是又要改这个新的指针。

操作系统中的内存管理应该是先把所有可用空间构造成链表,以后的分配回归就是对这个链表的删除和插入操作。已分配给程序,正在使用中的内存不做defragement.因为是内存,即使是碎片化也不会影响速度。

家园 是有问题,多谢指出,现有另一个思路

首先,这个问题来源是对XBOX/PS3编程的,相对内存比较紧张,而且对速度要求比较高,申请内存池的目的主要是减少对系统内存分配的请求,而内存池中的fragment随运行时间的增加,也是绝对不可忽视的。

经有人建议,采用老MAC OS的内存管理机制,使用双指针,不直接将内存地址返回给程序,而是维护一个地址列表,然后将地址列表中元素的地址返回给程序,这样OS可以在空余期间收集碎片,而程序需要dereference两次来取得实际地址。

我们在memory pool中建立一个Memory_pointer_table存储在pool中的地址

new返回MPTBL中的地址

defragment整理pool和MPTBL中指针值。应用程序allocate得到的指针不变。dereference后指向的内存内容不变。

代价是*是一定要重载的,如果要求支持数组的话,new[]和delete[]和数组下标[]也是要重载。

实现起来有一定困难,特别是类中的动态内存要用到的成员指针.*无法重载。限制了类中动态内存的应用。

不过起码是可以实现的方案。毕竟自己写个memory pool不能指望100%达到系统的功能

家园 去看看STL的内存管理方法
家园 一点想法

如果需要分派的内存符合一些条件

1:可以大致知道每次分配大约有多少

2:分配的大小差别不大

3:内存池容纳的片数不算太多

我觉得可以考虑这样处理

预先把内存池按照一定大小分配成N块,每块大致是常见的大小略有富裕,new的时候直接返回一块。如果已经用尽池内的,可以考率扩大池。内存回收的时候也暂时不交OS回收,而是下次分给别的应用。

这样不需要重载reference和derefrence操作,如果需要的话可考虑重载sizeof或者要越界检查的操作。

当然如果有频繁的小内存需要分配,可能这个办法不好。

在做游戏么?不知道什么类型的,说不定会买一款支持一下,赫赫

全看树展主题 · 分页首页 上页
/ 1
下页 末页


有趣有益,互惠互利;开阔视野,博采众长。
虚拟的网络,真实的人。天南地北客,相逢皆朋友

Copyright © cchere 西西河