admin管理员组文章数量:1567529
2024年7月12日发(作者:)
4/28/2015内存池设计与实现 shawn的专栏 博客频道
登录 | 注册
shawn的专栏
目录视图摘要视图订阅
个人资料
Markdown博文大赛清新开启 天天爱答题 一大波C币袭来 寻找Java大牛! 一次拿下软考,我自有锦囊妙计!
内存池设计与实现
分类: C/C++
20110629 14:37 20409人阅读 评论(16) 收藏 举报
nulliteratorbyteintegerstructbuffer
目录(?)[+]
shawngucas
1. 内存池设计
1.1 目的
访问:
25832次
在给定的内存buffer上建立内存管理机制,根据用户需求从该buffer上分配内存或者将已经分配的内存释放回
积分:
296
buffer中。
等级:
排名:千里之外
1.2 要求
原创:
4篇
转载:
3篇
尽量减少内存碎片,平均效率高于C语言的malloc和free。
译文:
0篇
评论:
18条
1.3 设计思路
文章搜索
将buffer分为四部分,第1部分是mem_pool结构体;第2部分是内存映射表;第3部分是内存chunk结构体缓冲
区;第4部分是实际可分配的内存区。整个buffer结构图如图1所示:
文章分类
C/C++(1)
Tips(4)
调试
(2)
文章存档
2011年07月(6)
2011年06月(1)
阅读排行
内存池设计与实现
(20368)
vs2008 工程配置路径设置(1884)
socket关闭过程(627)
图1 内存buffer结构图
关于lib和dll
(612)
第1部分的作用是可以通过该mem_pool结构体控制整个内存池。
Visual Studio 调试小技巧(396)
Vs 2008 使用技巧系列(294)
第2部分的作用是记录第4部分,即实际可分配的内存区的使用情况。表中的每一个单元表示一个固定大小的内
调试术语
(244)
存块(block),多个连续的block组成一个chunk,每个block的详细结构如图2所示:
评论排行
内存池设计与实现
(16)
vs2008 工程配置路径设置(2)
关于lib和dll
(0)
socket关闭过程(0)
图2 memory block结构图
Vs 2008 使用技巧系列(0)
其中count表示该block后面的与该block同属于一个chunk的blokc的个数,start表示该block所在的chunk的起始block索
调试术语
(0)
引。其实start这个域只有在每个chunk的最后一个block中才会用到(用于从当前chunk寻找前一个chunk的起始位
Visual Studio 调试小技巧(0)
置),而pmem_chunk则是一个指针,指向一个mem_chunk结构体。任意一块大小的内存都会被取向上整到block大小
的整数倍。
/shawngucas/article/details/65748631/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
推荐文章
第3部分是一个mem_chunk pool,其作用是存储整个程序可用的mem_chunk结构体。mem_chunk pool中的
mem_chunk被组织成双向链表结构(快速插入和删除)。每个mem_chunk结构图如图3所示:
* 【ShaderToy】开篇
* FFmpeg源代码简单分析:
avio_open2()
* 技能树之旅: 从模块分离到测试
* Qt5官方demo解析集36——
Wiggly Example
* Unity3d HDR和Bloom效果(高
动态范围图像和泛光)
图3 memory chunk结构图
* Android的Google官方设计指南
(上)
其中pmem_block指向该chunk在内存映射表中的位置,others表示其他一些域,不同的实现对应该域的内容略有不
同。
最新评论
内存池设计与实现
第4部分就是实际可以被分配给用户的内存。
erxiaodao: 好文章!请教下,性
能测试结果图是用什么工具画
的?
整个内存池管理程序除了这四部分外,还有一个重要的内容就是memory chunk set。虽然其中的每个元素都
内存池设计与实现
来自mem_chunk pool,但是它与mem_chunk pool的不同之处在于其中的每个memory chunk中记录了当前可用的
tifentan: 假设输入500M的内存被
管理的结构吃了100多M?不太
一块内存的相关信息。而mem_chunk pool中的memory chunk的内容是无定以的。可以这样理解mem_chunk pool
科学啊。
与memory chunk set:mem_chunk pool是为memory chunk set分配内存的“内存池”,只是该“内存池”每次分配的
内存池设计与实现
it_child: 或者说315行的size_t
内存大小是固定的,为mem_chunk结构体的大小。内存池程序主要是通过搜索这个memory chunk set来获取可被
index = pre_block>count;应该
改成
分配的内存。在memory chunk set上建立不同的数据结构就构成了不同的内存池实现方法,同时也导致了不同的搜
内存池设计与实现
索效率,直接影响内存池的性能,本文稍后会介绍两种内存池的实现。
it_child: void FreeMemory(void
*ptrMemoryBlock,
PMEMORYPOOL ...
1.4 内存池管理程序运行过程
内存池设计与实现
樱花树樱花开: 今天刚刚学了 操
初始化:内存映射表中只有一块可用的内存信息,大小为内存池中所有可用的内存。从memory chunk pool
作系统中的 内存管理...~我怎么
就没想到 把操作系统中的这种内
中分配一个mem_chunk,使其指向内存映射表中的第一个block,并根据具体的内存池实现方式填充
存管理来这样使用呢~...
mem_chunk中的其他域,然后将该mem_chunk添加到memory chunk set中。
内存池设计与实现
cyxHehui:
申请内存:当用户申请一块内存时,首先在memory chunk set中查找合适的内存块。如果找到符合要求的内
hi,mem_map_pool_count和
mem_map_unit_count分别是什
存块,就在内存映射表中找到相应的chunk,并修改chunk中相应block结构体的内容,然后根据修改后的
么呀?你在c...
chunk修改memory chunk set中chunk的内容,最后返回分配内存的起始地址;否则返回NULL。
内存池设计与实现
whdugh: 膜拜楼主 牛比
释放内存:当用户释放一块内存时,首先根据这块内存的起始地址找到其在内存映射表中对应的chunk,然后
内存池设计与实现
尝试将该chunk和与其相邻的chunk合并,修改chunk中相应block的内容并修改memory chunk set中相应
高鹏0071: 整理这么多,辛苦楼
主了啊。
chunk的内容或者向memory chunk set加入新的mem_chunk(这种情况在不能合并内存是发生)。
内存池设计与实现
头头: 当然我是在多线程下面测试
1.5 减少内存碎片
的,我对两个分配函数有座同步
处理
本文设计的方法只能在一定程度上减少内存碎片,并不能彻底消除内存碎片。具体方法如下:
内存池设计与实现
头头: 楼主,你这个有重大bug,当
连续分配2 块以上的内存的时
在用户释放内存时,尝试将该内存与其相邻的内存合并。如果其相邻内存为未分配内存则合并成功,合并后作
候,然后再来释放,就内存泄
露,bug了
为一整块内存使用;如火其相邻内存为已分配内存则不能合并,该释放的内存块作为一个独立的内存块被使用。
2 内存池实现链表结构
2.1 性能分析
链表结构的内存池实现是指将memory chunk set实现为双链表结构。这种方法的优缺点如下:
优点:释放内存很快,O(1)复杂度。
缺点:分配内存较慢,O(n)复杂度。
2.2 内存池运行状态转移图
绿色表示未使用的内存,红色表示已经使用的内存。其中每个block表示64B,这个值可以根据具体需要设定。
初始化
/shawngucas/article/details/65748632/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
图4 内存池初始化状态
申请内存
图5 第1次申请128B内存后
图6 第n次申请、释放内存后
释放内存
图7 释放64B内存前后
3 内存池实现大顶堆结构
3.1 性能分析
大顶堆结构的内存池实现是指将memory chunk set实现为大顶堆结构。这种方法的优缺点如下:
优点:降低了分配内存的时间复杂度,O(log(n))。
/shawngucas/article/details/65748633/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
缺点:增加了释放内存的时间复杂度,O(log(n))。
3.2 内存池运行状态转移图
绿色表示未使用的内存,红色表示已经使用的内存。其中每个block表示64B,这个值可以根据具体需要设定。
初始化
图8 内存池初始化状态
申请内存
图9 第1次申请128B内存后
图10 第n次申请、释放内存后
释放内存
/shawngucas/article/details/65748634/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
图11 释放64B内存前后
4 性能测试
测试对象:C语言的malloc、free和本文的两种内存池(大小为500M,实际可分配内存为310M)。
测试指标:执行n=2000次随机分配、释放随机大小内存(范围为64B~1024B)的时间比。
测试方法1:
(1) 生成n个随机数,大小在64~1024之间,用于表示n个要分配的内存大小;
(2) 生成n个随机数,取值 为0或者1,表示每次分配内存后紧接着是否释放内存;
(3) 测量C语言的malloc、free和本文两种内存池执行n次随机分配、释放随机大小内存的时间比ratio;
(4) 重复(3)m=200次,记录每次活动的ratio,并绘制相应的曲线。
测试方法2:
(1) 生成n个随机数,大小在a~b之间(初始值a=64,b=1024),用于表示n个要分配的内存大小;
(2) 测量C语言的malloc、free和本文两种内存池执行n次分配、释放随机大小内存的时间比ratio;
(3) 重复(2)m=512次,每次分配的内存容量的范围比前一次大1024B,记录每次获得的ratio,并绘制相
应曲线。
4.1 性能测试结果链表结果内存池
图12 链表结构内存池性能测试结果1
/shawngucas/article/details/65748635/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
图13 链表结构内存池性能测试结果2
4.2 性能测试结果大顶堆结构内存池
图14 大顶堆内存池性能测试结果1
图15 大顶堆内存池性能测试结果2
4.3 性能比较
图16 两种内存池性能测试结果比较1
/shawngucas/article/details/65748636/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
图17 两种内存池性能测试结果比较2
5 结论
从上面的内存池性能测试结果中可以看出,相比C语言的malloc和free,内存池使得用户分配内存和释放内存
的效率有了较大的提高,这一优势尤其分配较大快的内存时体现的尤为突出。
同时也可以看出大顶堆结够的内存池的性能并不比链表结构的内存池性能高,反而低于链表结构内存池的性
能。这再一次表明O(log(n))优于O(n)是有条件的。当然,本文的测试具有一定的局限性,也许在其他的测试案例中
大顶堆结构的内存池性能会超越链表结构的内存池。
附:源代码
链表结构内存池:
MemoryPool.h
[cpp]
01. #ifndef _MEMORYPOOL_H
02. #define _MEMORYPOOL_H
03. #include
04. #define MINUNITSIZE 64
05. #define ADDR_ALIGN 8
06. #define SIZE_ALIGN MINUNITSIZE
07. struct memory_chunk;
08. typedef struct memory_block
09. {
10. size_t count;
11. size_t start;
12. memory_chunk* pmem_chunk;
13. }memory_block;
14. // 可用的内存块结构体
15. typedef struct memory_chunk
16. {
17. memory_block* pfree_mem_addr;
18. memory_chunk* pre;
19. memory_chunk* next;
20. }memory_chunk;
21. // 内存池结构体
22. typedef struct MEMORYPOOL
23. {
24. void *memory;
25. size_t size;
26. memory_block* pmem_map;
27. memory_chunk* pfree_mem_chunk;
28. memory_chunk* pfree_mem_chunk_pool;
29. size_t mem_used_size; // 记录内存池中已经分配给用户的内存的大小
30. size_t mem_map_pool_count; // 记录链表单元缓冲池中剩余的单元的个数,个数为0时不能分配单元给
pfree_mem_chunk
31. size_t free_mem_chunk_count; // 记录 pfree_mem_chunk链表中的单元个数
32. size_t mem_map_unit_count; //
33. size_t mem_block_count; // 一个 mem_unit 大小为 MINUNITSIZE
34. }MEMORYPOOL, *PMEMORYPOOL;
35. /************************************************************************/
36. /* 生成内存池
37. * pBuf: 给定的内存buffer起始地址
38. * sBufSize: 给定的内存buffer大小
39. * 返回生成的内存池指针
40. /************************************************************************/
41. PMEMORYPOOL CreateMemoryPool(void* pBuf, size_t sBufSize);
42. /************************************************************************/
43. /* 暂时没用
44. /************************************************************************/
45. void ReleaseMemoryPool(PMEMORYPOOL* ppMem) ;
46. /************************************************************************/
47. /* 从内存池中分配指定大小的内存
48. * pMem: 内存池 指针
49. * sMemorySize: 要分配的内存大小
50. * 成功时返回分配的内存起始地址,失败返回NULL
51. /************************************************************************/
52. void* GetMemory(size_t sMemorySize, PMEMORYPOOL pMem) ;
53.
54. /************************************************************************/
55. /* 从内存池中释放申请到的内存
56. * pMem:内存池指针
57. * ptrMemoryBlock:申请到的内存起始地址
58. /************************************************************************/
59. void FreeMemory(void *ptrMemoryBlock, PMEMORYPOOL pMem) ;
60.
61. #endif //_MEMORYPOOL_H
/shawngucas/article/details/65748637/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
[cpp]
01. #include "stdafx.h"
02. #include
03. #include "MemoryPool.h"
04. /************************************************************************/
05. /* 内存池起始地址对齐到ADDR_ALIGN字节
06. /************************************************************************/
07. size_t check_align_addr(void*& pBuf)
08. {
09. size_t align = 0;
10. size_t addr = (int)pBuf;
11. align = (ADDR_ALIGN ‐ addr % ADDR_ALIGN) % ADDR_ALIGN;
12. pBuf = (char*)pBuf + align;
13. return align;
14. }
15. /************************************************************************/
16. /* 内存block大小对齐到MINUNITSIZE字节
17. /************************************************************************/
18. size_t check_align_block(size_t size)
19. {
20. size_t align = size % MINUNITSIZE;
21.
22. return size ‐ align;
23. }
24. /************************************************************************/
25. /* 分配内存大小对齐到SIZE_ALIGN字节
26. /************************************************************************/
27. size_t check_align_size(size_t size)
28. {
29. size = (size + SIZE_ALIGN ‐ 1) / SIZE_ALIGN * SIZE_ALIGN;
30. return size;
31. }
32. /************************************************************************/
33. /* 以下是链表相关操作
34. /************************************************************************/
35. memory_chunk* create_list(memory_chunk* pool, size_t count)
36. {
37. if (!pool)
38. {
39. return NULL;
40. }
41. memory_chunk* head = NULL;
42. for (size_t i = 0; i < count; i++)
43. {
44. pool‐>pre = NULL;
45. pool‐>next = head;
46. if (head != NULL)
47. {
48. head‐>pre = pool;
49. }
50. head = pool;
51. pool++;
52. }
53. return head;
54. }
55. memory_chunk* front_pop(memory_chunk*& pool)
56. {
57. if (!pool)
58. {
59. return NULL;
60. }
61. memory_chunk* tmp = pool;
62. pool = tmp‐>next;
63. pool‐>pre = NULL;
64. return tmp;
65. }
66. void push_back(memory_chunk*& head, memory_chunk* element)
67. {
68. if (head == NULL)
69. {
70. head = element;
71. head‐>pre = element;
72. head‐>next = element;
73. return;
74. }
75. head‐>pre‐>next = element;
76. element‐>pre = head‐>pre;
77. head‐>pre = element;
78. element‐>next = head;
79. }
80. void push_front(memory_chunk*& head, memory_chunk* element)
/shawngucas/article/details/65748638/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
81. {
82. element‐>pre = NULL;
83. element‐>next = head;
84. if (head != NULL)
85. {
86. head‐>pre = element;
87. }
88. head = element;
89. }
90. void delete_chunk(memory_chunk*& head, memory_chunk* element)
91. {
92. // 在双循环链表中删除元素
93. if (element == NULL)
94. {
95. return;
96. }
97. // element为链表头
98. else if (element == head)
99. {
100. // 链表只有一个元素
101. if (head‐>pre == head)
102. {
103. head = NULL;
104. }
105. else
106. {
107. head = element‐>next;
108. head‐>pre = element‐>pre;
109. head‐>pre‐>next = head;
110. }
111. }
112. // element为链表尾
113. else if (element‐>next == head)
114. {
115. head‐>pre = element‐>pre;
116. element‐>pre‐>next = head;
117. }
118. else
119. {
120. element‐>pre‐>next = element‐>next;
121. element‐>next‐>pre = element‐>pre;
122. }
123. element‐>pre = NULL;
124. element‐>next = NULL;
125. }
126. /************************************************************************/
127. /* 内存映射表中的索引转化为内存起始地
址
128. /************************************************************************/
129. void* index2addr(PMEMORYPOOL mem_pool, size_t index)
130. {
131. char* p = (char*)(mem_pool‐>memory);
132. void* ret = (void*)(p + index *MINUNITSIZE);
133.
134. return ret;
135. }
136. /************************************************************************/
137. /* 内存起始地址转化为内存映射表中的索
引
138. /************************************************************************/
139. size_t addr2index(PMEMORYPOOL mem_pool, void* addr)
140. {
141. char* start = (char*)(mem_pool‐>memory);
142. char* p = (char*)addr;
143. size_t index = (p ‐ start) / MINUNITSIZE;
144. return index;
145. }
146. /************************************************************************/
147. /* 生成内存池
148. * pBuf: 给定的内存buffer起始地址
149. * sBufSize: 给定的内存buffer大小
150. * 返回生成的内存池指针
151. /************************************************************************/
152. PMEMORYPOOL CreateMemoryPool(void* pBuf, size_t sBufSize)
153. {
154. memset(pBuf, 0, sBufSize);
155. PMEMORYPOOL mem_pool = (PMEMORYPOOL)pBuf;
156. // 计算需要多少memory map单元格
157. size_t mem_pool_struct_size = sizeof(MEMORYPOOL);
158. mem_pool‐
>mem_map_pool_count = (sBufSize ‐ mem_pool_struct_size + MINUNITSIZE ‐ 1) / MINUNITSIZE;
159. mem_pool‐
>mem_map_unit_count = (sBufSize ‐ mem_pool_struct_size + MINUNITSIZE ‐ 1) / MINUNITSIZE;
160. mem_pool‐>pmem_map = (memory_block*)((char*)pBuf + mem_pool_struct_size);
161. mem_pool‐>pfree_mem_chunk_pool = (memory_chunk*)
((char*)pBuf + mem_pool_struct_size + sizeof(memory_block) * mem_pool‐>mem_map_unit_count);
162.
/shawngucas/article/details/65748639/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
163. mem_pool‐>memory = (char*)pBuf + mem_pool_struct_size+ sizeof(memory_block) * mem_pool‐
>mem_map_unit_count + sizeof(memory_chunk) * mem_pool‐>mem_map_pool_count;
164. mem_pool‐>size = sBufSize ‐ mem_pool_struct_size ‐ sizeof(memory_block) * mem_pool‐
>mem_map_unit_count ‐ sizeof(memory_chunk) * mem_pool‐>mem_map_pool_count;
165. size_t align = check_align_addr(mem_pool‐>memory);
166. mem_pool‐>size ‐= align;
167. mem_pool‐>size = check_align_block(mem_pool‐>size);
168. mem_pool‐>mem_block_count = mem_pool‐>size / MINUNITSIZE;
169. // 链表化
170. mem_pool‐>pfree_mem_chunk_pool = create_list(mem_pool‐>pfree_mem_chunk_pool, mem_pool‐
>mem_map_pool_count);
171. // 初始化 pfree_mem_chunk,双向循环链表
172. memory_chunk* tmp = front_pop(mem_pool‐>pfree_mem_chunk_pool);
173. tmp‐>pre = tmp;
174. tmp‐>next = tmp;
175. tmp‐>pfree_mem_addr = NULL;
176. mem_pool‐>mem_map_pool_count‐‐;
177.
178. // 初始化 pmem_map
179. mem_pool‐>pmem_map[0].count = mem_pool‐>mem_block_count;
180. mem_pool‐>pmem_map[0].pmem_chunk = tmp;
181. mem_pool‐>pmem_map[mem_pool‐>mem_block_count‐1].start = 0;
182.
183. tmp‐>pfree_mem_addr = mem_pool‐>pmem_map;
184. push_back(mem_pool‐>pfree_mem_chunk, tmp);
185. mem_pool‐>free_mem_chunk_count = 1;
186. mem_pool‐>mem_used_size = 0;
187. return mem_pool;
188. }
189. /************************************************************************/
190. /* 暂时没用
191. /************************************************************************/
192. void ReleaseMemoryPool(PMEMORYPOOL* ppMem)
193. {
194. }
195. /************************************************************************/
196. /* 从内存池中分配指定大小的内存
197. * pMem: 内存池 指针
198. * sMemorySize: 要分配的内存大小
199. * 成功时返回分配的内存起始地址,失败返回NULL
200. /************************************************************************/
201. void* GetMemory(size_t sMemorySize, PMEMORYPOOL pMem)
202. {
203. sMemorySize = check_align_size(sMemorySize);
204. size_t index = 0;
205. memory_chunk* tmp = pMem‐>pfree_mem_chunk;
206. for (index = 0; index < pMem‐>free_mem_chunk_count; index++)
207. {
208. if (tmp‐>pfree_mem_addr‐>count * MINUNITSIZE >= sMemorySize)
209. {
210. break;
211. }
212.
213. tmp = tmp‐>next;
214. }
215.
216. if (index == pMem‐>free_mem_chunk_count)
217. {
218. return NULL;
219. }
220. pMem‐>mem_used_size += sMemorySize;
221. if (tmp‐>pfree_mem_addr‐>count * MINUNITSIZE == sMemorySize)
222. {
223. // 当要分配的内存大小与当前chunk中的内存大小相同时,从pfree_mem_chunk链表中删除此chunk
224. size_t current_index = (tmp‐>pfree_mem_addr ‐ pMem‐>pmem_map);
225. delete_chunk(pMem‐>pfree_mem_chunk, tmp);
226. tmp‐>pfree_mem_addr‐>pmem_chunk = NULL;
227.
228. push_front(pMem‐>pfree_mem_chunk_pool, tmp);
229. pMem‐>free_mem_chunk_count‐‐;
230. pMem‐>mem_map_pool_count++;
231.
232. return index2addr(pMem, current_index);
233. }
234. else
235. {
236. // 当要分配的内存小于当前chunk中的内存时,更改pfree_mem_chunk中相应chunk的pfree_mem_addr
237.
238. // 复制当前mem_map_unit
239. memory_block copy;
240. = tmp‐>pfree_mem_addr‐>count;
241. _chunk = tmp;
242. // 记录该block的起始和结束索引
243. memory_block* current_block = tmp‐>pfree_mem_addr;
244. current_block‐>count = sMemorySize / MINUNITSIZE;
245. size_t current_index = (current_block ‐ pMem‐>pmem_map);
246. pMem‐>pmem_map[current_index+current_block‐>count‐1].start = current_index;
/shawngucas/article/details/657486310/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
247. current_block‐>pmem_chunk = NULL; // NULL表示当前内存块已被分配
248. // 当前block被一分为二,更新第二个block中的内容
249. pMem‐>pmem_map[current_index+current_block‐>count].count = ‐ current_block‐
>count;
250. pMem‐>pmem_map[current_index+current_block‐>count].pmem_chunk = _chunk;
251. // 更新原来的pfree_mem_addr
252. tmp‐>pfree_mem_addr = &(pMem‐>pmem_map[current_index+current_block‐>count]);
253.
254. size_t end_index = current_index + ‐ 1;
255. pMem‐>pmem_map[end_index].start = current_index + current_block‐>count;
256. return index2addr(pMem, current_index);
257. }
258. }
259. /************************************************************************/
260. /* 从内存池中释放申请到的内存
261. * pMem:内存池指针
262. * ptrMemoryBlock:申请到的内存起始地址
263. /************************************************************************/
264. void FreeMemory(void *ptrMemoryBlock, PMEMORYPOOL pMem)
265. {
266. size_t current_index = addr2index(pMem, ptrMemoryBlock);
267. size_t size = pMem‐>pmem_map[current_index].count * MINUNITSIZE;
268. // 判断与当前释放的内存块相邻的内存块是否可以与当前释放的内存块合并
269. memory_block* pre_block = NULL;
270. memory_block* next_block = NULL;
271. memory_block* current_block = &(pMem‐>pmem_map[current_index]);
272. // 第一个
273. if (current_index == 0)
274. {
275. if (current_block‐>count < pMem‐>mem_block_count)
276. {
277. next_block = &(pMem‐>pmem_map[current_index+current_block‐>count]);
278. // 如果后一个内存块是空闲的,合并
279. if (next_block‐>pmem_chunk != NULL)
280. {
281. next_block‐>pmem_chunk‐>pfree_mem_addr = current_block;
282. pMem‐>pmem_map[current_index+current_block‐>count+next_block‐>count‐
1].start = current_index;
283. current_block‐>count += next_block‐>count;
284. current_block‐>pmem_chunk = next_block‐>pmem_chunk;
285. next_block‐>pmem_chunk = NULL;
286. }
287. // 如果后一块内存不是空闲的,在pfree_mem_chunk中增加一个chunk
288. else
289. {
290. memory_chunk* new_chunk = front_pop(pMem‐>pfree_mem_chunk_pool);
291. new_chunk‐>pfree_mem_addr = current_block;
292. current_block‐>pmem_chunk = new_chunk;
293. push_back(pMem‐>pfree_mem_chunk, new_chunk);
294. pMem‐>mem_map_pool_count‐‐;
295. pMem‐>free_mem_chunk_count++;
296. }
297. }
298. else
299. {
300. memory_chunk* new_chunk = front_pop(pMem‐>pfree_mem_chunk_pool);
301. new_chunk‐>pfree_mem_addr = current_block;
302. current_block‐>pmem_chunk = new_chunk;
303. push_back(pMem‐>pfree_mem_chunk, new_chunk);
304. pMem‐>mem_map_pool_count‐‐;
305. pMem‐>free_mem_chunk_count++;
306. }
307. }
308.
309. // 最后一个
310. else if (current_index == pMem‐>mem_block_count‐1)
311. {
312. if (current_block‐>count < pMem‐>mem_block_count)
313. {
314. pre_block = &(pMem‐>pmem_map[current_index‐1]);
315. size_t index = pre_block‐>count;
316. pre_block = &(pMem‐>pmem_map[index]);
317.
318. // 如果前一个内存块是空闲的,合并
319. if (pre_block‐>pmem_chunk != NULL)
320. {
321. pMem‐>pmem_map[current_index+current_block‐>count‐
1].start = current_index ‐ pre_block‐>count;
322. pre_block‐>count += current_block‐>count;
323. current_block‐>pmem_chunk = NULL;
324. }
325. // 如果前一块内存不是空闲的,在pfree_mem_chunk中增加一个chunk
326. else
327. {
328. memory_chunk* new_chunk = front_pop(pMem‐>pfree_mem_chunk_pool);
329. new_chunk‐>pfree_mem_addr = current_block;
330. current_block‐>pmem_chunk = new_chunk;
/shawngucas/article/details/657486311/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
331. push_back(pMem‐>pfree_mem_chunk, new_chunk);
332. pMem‐>mem_map_pool_count‐‐;
333. pMem‐>free_mem_chunk_count++;
334. }
335. }
336. else
337. {
338. memory_chunk* new_chunk = front_pop(pMem‐>pfree_mem_chunk_pool);
339. new_chunk‐>pfree_mem_addr = current_block;
340. current_block‐>pmem_chunk = new_chunk;
341. push_back(pMem‐>pfree_mem_chunk, new_chunk);
342. pMem‐>mem_map_pool_count‐‐;
343. pMem‐>free_mem_chunk_count++;
344. }
345. }
346. else
347. {
348. next_block = &(pMem‐>pmem_map[current_index+current_block‐>count]);
349. pre_block = &(pMem‐>pmem_map[current_index‐1]);
350. size_t index = pre_block‐>start;
351. pre_block = &(pMem‐>pmem_map[index]);
352. bool is_back_merge = false;
353. if (next_block‐>pmem_chunk == NULL && pre_block‐>pmem_chunk == NULL)
354. {
355. memory_chunk* new_chunk = front_pop(pMem‐>pfree_mem_chunk_pool);
356. new_chunk‐>pfree_mem_addr = current_block;
357. current_block‐>pmem_chunk = new_chunk;
358. push_back(pMem‐>pfree_mem_chunk, new_chunk);
359. pMem‐>mem_map_pool_count‐‐;
360. pMem‐>free_mem_chunk_count++;
361. }
362. // 后一个内存块
363. if (next_block‐>pmem_chunk != NULL)
364. {
365. next_block‐>pmem_chunk‐>pfree_mem_addr = current_block;
366. pMem‐>pmem_map[current_index+current_block‐>count+next_block‐>count‐
1].start = current_index;
367. current_block‐>count += next_block‐>count;
368. current_block‐>pmem_chunk = next_block‐>pmem_chunk;
369. next_block‐>pmem_chunk = NULL;
370. is_back_merge = true;
371. }
372. // 前一个内存块
373. if (pre_block‐>pmem_chunk != NULL)
374. {
375. pMem‐>pmem_map[current_index+current_block‐>count‐
1].start = current_index ‐ pre_block‐>count;
376. pre_block‐>count += current_block‐>count;
377. if (is_back_merge)
378. {
379. delete_chunk(pMem‐>pfree_mem_chunk, current_block‐>pmem_chunk);
380. push_front(pMem‐>pfree_mem_chunk_pool, current_block‐>pmem_chunk);
381. pMem‐>free_mem_chunk_count‐‐;
382. pMem‐>mem_map_pool_count++;
383. }
384. current_block‐>pmem_chunk = NULL;
385. }
386. }
387. pMem‐>mem_used_size ‐= size;
388. }
[cpp]
01. // memory pool : Defines the entry point for the console application.
02. #include
03. #include "MemoryPool.h"
04. #include
05. #include
06. #include
07. #include
08. #include
09. #include
10. using namespace std;
11. int break_time = 0;
12. // 检测内存池相关参数
13. void check_mem_pool(int& max_chunk_size, int& free_chunk_count, int& min_chunk_size, int& total_free_mem, MEMORYPOOL* m
14. {
15. memory_chunk* head = mem_pool‐>pfree_mem_chunk;
16. memory_chunk* tmp = head;
17. free_chunk_count = 0;
18. total_free_mem = 0;
19. max_chunk_size = 0;
/shawngucas/article/details/657486312/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
20. min_chunk_size = 500*1024*1024;
21. if (head == NULL)
22. {
23. min_chunk_size = 0;
24. return;
25. }
26. while (tmp‐>next != head)
27. {
28. free_chunk_count++;
29. total_free_mem += tmp‐>pfree_mem_addr‐>count * MINUNITSIZE;
30. if (tmp‐>pfree_mem_addr‐>count * MINUNITSIZE > max_chunk_size )
31. {
32. max_chunk_size = tmp‐>pfree_mem_addr‐>count * MINUNITSIZE;
33. }
34. if (tmp‐>pfree_mem_addr‐>count * MINUNITSIZE < min_chunk_size)
35. {
36. min_chunk_size = tmp‐>pfree_mem_addr‐>count * MINUNITSIZE;
37. }
38. tmp = tmp‐>next;
39. }
40. free_chunk_count++;
41. total_free_mem += tmp‐>pfree_mem_addr‐>count * MINUNITSIZE;
42. if (tmp‐>pfree_mem_addr‐>count * MINUNITSIZE > max_chunk_size )
43. {
44. max_chunk_size = tmp‐>pfree_mem_addr‐>count * MINUNITSIZE;
45. }
46. if (tmp‐>pfree_mem_addr‐>count * MINUNITSIZE < min_chunk_size)
47. {
48. min_chunk_size = tmp‐>pfree_mem_addr‐>count * MINUNITSIZE;
49. }
50. }
51. // 申请后紧接着释放
52. double test_mem_pool_perf_1(PMEMORYPOOL mem_pool, int iter, int* sizes)
53. {
54. cout << "*********************test_mem_pool_perf_1*********************" << endl;
55. LARGE_INTEGER litmp;
56. LONGLONG QPart1, QPart2;
57. double t;
58. double dfMinus, dfFreq;
59. QueryPerformanceFrequency(&litmp);
60. dfFreq = (double)rt;// 获得计数器的时钟频率
61. QueryPerformanceCounter(&litmp);
62. QPart1 = rt;// 获得初始值
63. for (int i = 0; i < iter; i++)
64. {
65. void *p = GetMemory(sizes[i], mem_pool);
66. if (p == NULL)
67. {
68. cout << "break @ iterator = " << i << " / " << iter << ", need memory " << sizes[i] <<
69. cout << "total memory is: " << mem_pool‐>size << " Byte" << endl;
70. cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl;
71. cout << "memory left is: " << mem_pool‐>size ‐ mem_pool‐
>mem_used_size << endl << endl;
72. int max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem;
73. check_mem_pool(max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem, mem_pool);
74. cout << "check memory pool result:" << endl;
75. cout << "free_chunk_count: " << free_chunk_count << endl
76. << "total_free_mem: " << total_free_mem << endl
77. << "max_chunk_size: " << max_chunk_size << endl
78. << "min_chunk_size: " << min_chunk_size << endl;
79. break;
80. }
81. FreeMemory(p, mem_pool);
82. }
83. QueryPerformanceCounter(&litmp);
84. QPart2 = rt;//获得中止值
85. dfMinus = (double)(QPart2‐QPart1);
86. t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
87. cout << "test_mem_pool_perf_1: iter = " << iter << endl;
88. cout << "time: " << t << endl;
89. cout << "*********************test_mem_pool_perf_1*********************" << endl << endl << endl;
90. return t;
91. }
92. double test_std_perf_1(int iter, int* sizes)
93. {
94. cout << "*********************test_std_perf_1*********************" << endl;
95. LARGE_INTEGER litmp;
96. LONGLONG QPart1, QPart2;
97. double t;
98. double dfMinus, dfFreq;
99. QueryPerformanceFrequency(&litmp);
100. dfFreq = (double)rt;// 获得计数器的时钟频率
101. QueryPerformanceCounter(&litmp);
102. QPart1 = rt;// 获得初始值
103. for (int i = 0; i < iter; i++)
104. {
105. void *p = malloc(sizes[i]);
/shawngucas/article/details/657486313/32
4/28/2015
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
内存池设计与实现 shawn的专栏 博客频道
if (p == NULL)
{
cout << "break @ iterator = " << i << " / " << iter << ", need memory " << sizes[i] <<
break;
}
free(p);
}
QueryPerformanceCounter(&litmp);
QPart2 = rt;//获得中止值
dfMinus = (double)(QPart2‐QPart1);
t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
cout << "test_std_perf_1: iter = " << iter << endl;
cout << "time: " << t << endl;
cout << "*********************test_std_perf_1*********************" << endl << endl << endl;
120. return t;
121. }
122. // 连续申请iter/2次,然后释放所有申请内存;再重复一次
123. double test_mem_pool_perf_2(PMEMORYPOOL mem_pool, int iter, int size)
124. {
125. cout << "*********************test_mem_pool_perf_2*********************" << endl;
126. LARGE_INTEGER litmp;
127. LONGLONG QPart1, QPart2;
128. double t;
129. double dfMinus, dfFreq;
130. QueryPerformanceFrequency(&litmp);
131. dfFreq = (double)rt;// 获得计数器的时钟频率
132. QueryPerformanceCounter(&litmp);
133. QPart1 = rt;// 获得初始值
134. void **p = new void*[iter];
135. if (p == NULL)
136. {
137. cout << "new faild" << endl;
138. return ‐1;
139. }
140. int count = 0;
141. for (int i = 0; i < iter/2; i++)
142. {
143. p[i] = GetMemory(size, mem_pool);
144. if (p[i] == NULL)
145. {
146. cout << "break @ iterator = " << i << " / " << iter << ", need memory " << size <<
147. cout << "total memory is: " << mem_pool‐>size << " Byte" << endl;
148. cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl;
149. cout << "memory left is: " << mem_pool‐>size ‐ mem_pool‐
>mem_used_size << endl << endl;
150. int max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem;
151. check_mem_pool(max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem, mem_pool);
152. cout << "check memory pool result:" << endl;
153. cout << "free_chunk_count: " << free_chunk_count << endl
154. << "total_free_mem: " << total_free_mem << endl
155. << "max_chunk_size: " << max_chunk_size << endl
156. << "min_chunk_size: " << min_chunk_size << endl;
157. break;
158. }
159. count++;
160. }
161. for (int i = 0; i < count; i++)
162. {
163. FreeMemory(p[i], mem_pool);
164. }
165. count = 0;
166. for (int i = 0; i < iter/2; i++)
167. {
168. p[i] = GetMemory(size, mem_pool);
169. if (p[i] == NULL)
170. {
171. cout << "break @ iterator = " << i << " / " << iter << ", need memory " << size <<
172. cout << "total memory is: " << mem_pool‐>size << " Byte" << endl;
173. cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl;
174. cout << "memory left is: " << mem_pool‐>size ‐ mem_pool‐
>mem_used_size << endl << endl;
175.
176. int max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem;
177. check_mem_pool(max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem, mem_pool);
178. cout << "check memory pool result:" << endl;
179. cout << "free_chunk_count: " << free_chunk_count << endl
180. << "total_free_mem: " << total_free_mem << endl
181. << "max_chunk_size: " << max_chunk_size << endl
182. << "min_chunk_size: " << min_chunk_size << endl;
183. break;
184. }
185. count++;
186. }
187. for (int i = 0; i < count; i++)
188. {
189. if (p[i] == NULL)
190. {
/shawngucas/article/details/657486314/32
4/28/2015
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
内存池设计与实现 shawn的专栏 博客频道
cout << i << endl;
break;
}
FreeMemory(p[i], mem_pool);
}
QueryPerformanceCounter(&litmp);
QPart2 = rt;//获得中止值
dfMinus = (double)(QPart2‐QPart1);
t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
cout << "test_mem_pool_perf_2: iter = " << iter << endl;
cout << "time: " << t << endl;
delete []p;
cout << "*********************test_mem_pool_perf_2*********************" << endl << endl << endl;
204. return t;
205. }
206. // 连续申请inner_iter次,释放;重复iter/inner_iter次
207. double test_mem_pool_perf_3(PMEMORYPOOL mem_pool, int iter, int size)
208. {
209. cout << "*********************test_mem_pool_perf_3*********************" << endl;
210. int inner_iter = 10;
211. void **p = new void*[inner_iter];
212. if (p == NULL)
213. {
214. cout << "new faild" << endl;
215. return ‐1;
216. }
217. LARGE_INTEGER litmp;
218. LONGLONG QPart1, QPart2, start, finish;
219. double t;
220. double dfMinus, dfFreq;
221. QueryPerformanceFrequency(&litmp);
222. dfFreq = (double)rt;// 获得计数器的时钟频率
223. QueryPerformanceCounter(&litmp);
224. QPart1 = rt;// 获得初始值
225. for (int k = 0; k < iter / inner_iter; k++)
226. {
227. int j = 0;
228. for (j = 0; j < inner_iter; j++)
229. {
230. p[j] = GetMemory(size, mem_pool);
231. if (p[j] == NULL)
232. {
233. cout << "break @ iterator = " << j << " / " << iter << ", need memory " << size <<
234. cout << "total memory is: " << mem_pool‐>size << " Byte" << endl;
235. cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl;
236. cout << "memory left is: " << mem_pool‐>size ‐ mem_pool‐
>mem_used_size << endl << endl;
237. int max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem;
238. check_mem_pool(max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem, mem_pool);
239. cout << "check memory pool result:" << endl;
240. cout << "free_chunk_count: " << free_chunk_count << endl
241. << "total_free_mem: " << total_free_mem << endl
242. << "max_chunk_size: " << max_chunk_size << endl
243. << "min_chunk_size: " << min_chunk_size << endl;
244. break;
245. }
246. }
247. for (int i = 0; i < j; i++)
248. {
249. FreeMemory(p[i], mem_pool);
250. }
251. }
252. QueryPerformanceCounter(&litmp);
253. QPart2 = rt;//获得中止值
254. dfMinus = (double)(QPart2‐QPart1);
255. t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
256. cout << "test_mem_pool_perf_3: iter = " << iter << endl;
257. cout << "time: " << t << endl;
258. cout << "*********************test_mem_pool_perf_3*********************" << endl << endl << endl;
259. return t;
260. }
261. // 随机内存大小,随机释放操作
262. double test_mem_pool_perf_rand(PMEMORYPOOL mem_pool, int iter, int* sizes, int* instruction)
263. {
264. cout << "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐test_mem_pool_perf_rand‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ "<< endl;
265. void** p = new void*[iter];
266. if (p == NULL)
267. {
268. cout << "new failed" << endl;
269. return ‐1;
270. }
271. LARGE_INTEGER litmp, gftime;
272. LONGLONG QPart1, QPart2, start, finish;
273. double t, GetMemory_time, FreeMemory_time;
274. double dfMinus, dfFreq;
275. QueryPerformanceFrequency(&litmp);
276. dfFreq = (double)rt;// 获得计数器的时钟频率
/shawngucas/article/details/657486315/32
4/28/2015
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
内存池设计与实现 shawn的专栏 博客频道
QueryPerformanceCounter(&litmp);
QPart1 = rt;// 获得初始值
int index = 0;
int size;
int free_tmp = 0;
double seach_time;
for (int i = 0; i < iter; i++)
{
size = sizes[i];
p[index++] = GetMemory(size, mem_pool);
if (p[index‐1] == NULL)
{
break_time++;
cout << "break @ iterator = " << i << " / " << iter << ", need memory " << size <<
cout << "total memory is: " << mem_pool‐>size << " Byte" << endl;
cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl;
cout << "memory left is: " << mem_pool‐>size ‐ mem_pool‐
>mem_used_size << endl << endl;
int max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem;
check_mem_pool(max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem, mem_pool);
296. cout << "check memory pool result:" << endl;
297. cout << "free_chunk_count: " << free_chunk_count << endl
298. << "total_free_mem: " << total_free_mem << endl
299. << "max_chunk_size: " << max_chunk_size << endl
300. << "min_chunk_size: " << min_chunk_size << endl;
301. break;
302. }
303.
304. if (instruction[i] == 1)
305. {
306. FreeMemory(p[‐‐index], mem_pool);
307. }
308. }
309. QueryPerformanceCounter(&litmp);
310. QPart2 = rt;//获得中止值
311. dfMinus = (double)(QPart2‐QPart1);
312. t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
313. cout << "test_mem_pool_perf_rand: iter = " << iter << endl;
314. cout << "time: " << t << endl << endl;
315. delete []p;
316. return t;
317. }
318. double test_std_perf(int iter, int* sizes, int* instruction)
319. {
320. cout << "test_std_perf" << endl;
321. void** p =new void*[iter];
322. if (p == NULL)
323. {
324. cout << "new failed" << endl;
325. return ‐1;
326. }
327.
328. LARGE_INTEGER litmp;
329. LONGLONG QPart1, QPart2;
330. double t;
331. double dfMinus, dfFreq;
332. QueryPerformanceFrequency(&litmp);
333. dfFreq = (double)rt;// 获得计数器的时钟频率
334. QueryPerformanceCounter(&litmp);
335. QPart1 = rt;// 获得初始值
336. // cout << "test start" << endl;
337. int index = 0;
338. int size;
339. for (int i = 0; i < iter; i++)
340. {
341. size = sizes[i];
342. p[index++] = malloc(size);
343. if (p[index‐1] == NULL)
344. {
345. cout << i << endl;
346. break;
347. }
348. if (instruction[i] == 1)
349. {
350. free(p[‐‐index]);
351. }
352. }
353. QueryPerformanceCounter(&litmp);
354. QPart2 = rt;//获得中止值
355. dfMinus = (double)(QPart2‐QPart1);
356. t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
357. cout << "test_std_perf: iter = " << iter << endl;
358. cout << "time: " << t << endl << endl;
359. for (int k = 0; k < index; k++)
360. {
361. free(p[k]);
362. }
/shawngucas/article/details/657486316/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
363. return t;
364. }
365. double test_std_perf_fix_size(int iter, int size)
366. {
367. cout << "******************* test_std_perf_fix_size *******************" << endl;
368. LARGE_INTEGER litmp;
369. LONGLONG QPart1, QPart2;
370. double t;
371. double dfMinus, dfFreq;
372. QueryPerformanceFrequency(&litmp);
373. dfFreq = (double)rt;// 获得计数器的时钟频率
374. QueryPerformanceCounter(&litmp);
375. QPart1 = rt;// 获得初始值
376. int index = 0;
377.
378. for (int i = 0; i < iter; i++)
379. {
380. void *p = malloc(size);
381. if (p == NULL)
382. {
383. cout << i << endl;
384. break;
385. }
386. free(p);
387. }
388. QueryPerformanceCounter(&litmp);
389. QPart2 = rt;//获得中止值
390. dfMinus = (double)(QPart2‐QPart1);
391. t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
392. cout << "test_std_perf: iter = " << iter << endl;
393. cout << "time: " << t << endl;
394. cout << "******************* test_std_perf_fix_size *******************" << endl << endl << endl;
395. return t;
396. }
397. void test_correct_1(PMEMORYPOOL mem_pool, int iter, int size)
398. {
399. vector
400. vector
401. int i = 0;
402. cout << "**************************** Get Memory Test Start ****************************"
<< endl << endl;
403. for (i = 0; i < iter; i++)
404. {
405. void *p = GetMemory(size, mem_pool);
406. if (p == NULL)
407. {
408. cout << "break @ iterator = " << i << " / " << iter << ", need memory " << size <<
409. cout << "memory left is: " << mem_pool‐>size << " Byte" << endl;
410. cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl << endl;
411. break;
412. }
413. _back(p);
414. }
415. cout << "break @ iterator = " << i << " / " << iter << ", need memory " << size << " Byte" << endl;
416. cout << "memory left is: " << mem_pool‐>size << " Byte" << endl;
417. cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl << endl;
418. cout << "verify memory size" << endl;
419. memory_chunk* tmp = mem_pool‐>pfree_mem_chunk;
420. int free_size = 0;
421. for (int k = 0; k < mem_pool‐>free_mem_chunk_count; k++)
422. {
423. free_size += tmp‐>pfree_mem_addr‐>count * MINUNITSIZE;
424. tmp = tmp‐>next;
425. }
426. cout << "memory free size is " << free_size << " Byte" << endl;
427. cout << "memory used size is " << mem_pool‐>mem_used_size << " Byte" << endl;
428. cout << "*************************** Get Memory Test Finish ***************************"
<< endl << endl;
429. cout << "*************************** Free Memory Test Start ***************************"
<< endl << endl;
430. int index = 0;
431. for (vec_iter = (); vec_iter != (); vec_iter++)
432. {
433. index++;
434. FreeMemory(*vec_iter, mem_pool);
435. }
436. cout << "memory left is: " << mem_pool‐>size << " Byte" << endl;
437. cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl << endl;
438. cout << "*************************** Free Memory Test Finish ***************************"
<< endl << endl;
439. cout << "********************* Get Memory Test (after Free) Start *********************"
<< endl << endl;
440. for (i = 0; i < iter; i++)
441. {
442. void *p = GetMemory(size, mem_pool);
443. if (p == NULL)
444. {
/shawngucas/article/details/657486317/32
4/28/2015
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
内存池设计与实现 shawn的专栏 博客频道
cout << "break @ iterator = " << i << " / " << iter << ", need memory " << size <<
cout << "memory left is: " << mem_pool‐>size << " Byte" << endl;
cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl << endl;
int max_size = 0;
memory_chunk* tmp = mem_pool‐>pfree_mem_chunk;
for (int k = 0; k < mem_pool‐>free_mem_chunk_count; k++)
{
if (tmp‐>pfree_mem_addr‐>count * MINUNITSIZE > max_size)
{
max_size = tmp‐>pfree_mem_addr‐>count * MINUNITSIZE > max_size;
}
}
cout << "max chunk size is: " << max_size << " Byte" << endl;
break;
}
_back(p);
}
cout << "break @ iterator = " << i << " / " << iter << ", need memory " << size << " Byte" << endl;
463. cout << "memory left is: " << mem_pool‐>size << " Byte" << endl;
464. cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl << endl;
465. cout << "verify memory size" << endl;
466. tmp = mem_pool‐>pfree_mem_chunk;
467. free_size = 0;
468. for (int k = 0; k < mem_pool‐>free_mem_chunk_count; k++)
469. {
470. free_size += tmp‐>pfree_mem_addr‐>count * MINUNITSIZE;
471. tmp = tmp‐>next;
472. }
473. cout << "memory free size is " << free_size << " Byte" << endl;
474. cout << "memory used size is " << mem_pool‐>mem_used_size << " Byte" << endl;
475. cout << "********************* Get Memory Test (after Free) Finish *********************"
<< endl << endl;
476. }
477. /************************************************************************/
478. /* 内存池性能测试代码
479. * 固定大小
480. /************************************************************************/
481. /*
482. void test_mem_pool_fix_size(PMEMORYPOOL mem_pool)
483. {
484. int iter = 200000;
485. int size = 512;
486. double t1 = test_std_perf_fix_size(iter, size);
487. double t2 = test_mem_pool_perf_1(mem_pool, iter, size);
488. double t3 = test_mem_pool_perf_2(mem_pool, iter, size);
489. double t4 = test_mem_pool_perf_3(mem_pool, iter, size);
490. cout << endl << endl
491. << "test count: " << iter << ", test size: " << size << endl
492. << "test result (system time / mem_pool time) : " << endl;
493. cout << "test_mem_pool_perf_1: " << t1 / t2 << endl
494. << "test_mem_pool_perf_2: " << t1 / t3 << endl
495. << "test_mem_pool_perf_3: " << t1 / t4 << endl;
496. }
497. */
498. /************************************************************************/
499. /* 内存池性能测试代码
500.
501. * 随机大小,随机释放操作
502. /************************************************************************/
503. void rand_test()
504. {
505. size_t sBufSize = 500* 1024*1024;
506. void*pBuf = malloc(sBufSize);
507. if (pBuf == NULL)
508. {
509. cout << "malloc failed" << endl;
510. return;
511. }
512. PMEMORYPOOL mem_pool = CreateMemoryPool(pBuf, sBufSize);
513. ofstream out("rand_");
514. int iter = 2000;
515. int* instruction = new int[iter];
516. int* sizes = new int[iter];
517. if (instruction == NULL || sizes == NULL)
518. {
519. cout << "new memory failed" << endl;
520. return;
521. }
522. srand(time(NULL));
523. cout << "generate rand number" << endl;
524. // instruction 中元素为1时表示在GetMemory后执行FreeMemory,0表示不执行FreeMemory
525. // sizes中是每次分配内存的大小,范围从64B~1024B
526. for (int i = 0; i < iter; i++)
527. {
528. instruction[i] = rand() % 2;
529. sizes[i] = (rand() % 16 + 1) * 64;
530. }
/shawngucas/article/details/657486318/32
4/28/2015
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
内存池设计与实现 shawn的专栏 博客频道
int test_count = 200;
double t1, t2;
double* ratio = new double[test_count];
int count = 0;
for (int k = 0; k < test_count; k++)
{
if (break_time != 0)
{
cout << "break @ " << k << " / " << test_count << endl;
break;
}
count++;
cout << "******************************************test " << k+1 << " *****************************************
544. t1 = test_std_perf(iter, sizes, instruction);
545. t2 = test_mem_pool_perf_rand(mem_pool, iter, sizes, instruction);
546. cout << "total memory: " << mem_pool‐>size << ", memory used: " << mem_pool‐
>mem_used_size
547. << ", memory left: " << mem_pool‐>size ‐ mem_pool‐>mem_used_size << endl;
548. ratio[k] = t1 / t2;
549.
550. }
551. if(break_time == 0)
552. break_time = test_count;
553. break_time = count ‐ 1;
554. cout << "*************************** ratio (system time / mem_pool time) ***************************"
555. for (int k = 0; k < break_time; k++)
556. {
557. out << ratio[k] << ",";
558. if (k % 10 == 0 && k != 0)
559. {
560. cout << endl;
561. }
562. cout << ratio[k] << " ";
563. }
564. cout << endl;
565. delete []ratio;
566. delete []instruction;
567. delete []sizes;
568. free(pBuf);
569. }
570. // 申请紧接着释放
571. void rand_test_2()
572. {
573. size_t sBufSize = 500* 1024*1024;
574. void*pBuf = malloc(sBufSize);
575. if (pBuf == NULL)
576. {
577. cout << "malloc failed" << endl;
578. return;
579. }
580. PMEMORYPOOL mem_pool = CreateMemoryPool(pBuf, sBufSize);
581. int iter = 2000;
582. int test_count = 511;
583. int* sizes = new int[iter];
584. double* ratio = new double[test_count];
585. if (sizes == NULL || ratio == NULL)
586. {
587. cout << "new memory failed" << endl;
588. return;
589. }
590. srand(time(NULL));
591. cout << "generate rand number" << endl;
592. ofstream out("rand_test_");
593. for (int k = 0; k < test_count; k++)
594. {
595. for (int i = 0; i < iter; i++)
596. {
597. sizes[i] = (rand() % 16 + 1) * 64 + 1024 * k;
598. }
599. double mem_pool_t = test_mem_pool_perf_1(mem_pool, iter, sizes);
600. double std_t = test_std_perf_1(iter, sizes);
601.
602. ratio[k] = std_t / mem_pool_t;
603. }
604. cout << "*************************** ratio (system time / mem_pool time) ***************************"
605. for (int k = 0; k < test_count; k++)
606. {
607. out << ratio[k] << ",";
608. if (k % 10 == 0 && k != 0)
609. {
610. cout << endl;
611. }
612. cout << ratio[k] << " ";
613. }
614. cout << endl;
615.
616. delete []sizes;
/shawngucas/article/details/657486319/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
617. delete ratio;
618. free(pBuf);
619. }
620. int _tmain(int argc, _TCHAR* argv[])
621. {
622. rand_test();
623. // rand_test_2();
624.
625. return 0;
626. }
大顶堆结构内存池:
MemoryPool.h
[cpp]
01. #ifndef _MEMORYPOOL_H
02. #define _MEMORYPOOL_H
03. #include
04. #define MINUNITSIZE 64
05. #define ADDR_ALIGN 8
06. #define SIZE_ALIGN MINUNITSIZE
07. #define MAXCHUNKSIZE 1024*1024*64
08. struct memory_chunk;
09. typedef struct memory_block
10. {
11. size_t count;
12. size_t start;
13. memory_chunk* pmem_chunk;
14. }memory_block;
15. typedef struct memory_chunk
16. {
17. size_t chunk_size;
18. memory_block* pfree_mem_addr;
19. }memory_chunk;
20. typedef struct max_heap
21. {
22. memory_chunk *heap;
23. size_t maxSize;
24. size_t currentSize;
25. }max_heap;
26. typedef struct MEMORYPOOL
27. {
28. void *memory;
29. size_t size;
30. memory_block* pmem_map;
31. max_heap heap;
32. size_t mem_used_size; // 记录内存池中已经分配给用户的内存的大小
33. size_t free_mem_chunk_count; // 记录 pfree_mem_chunk链表中的单元个数
34. size_t mem_map_unit_count; //
35. size_t mem_block_count; // 一个 mem_unit 大小为 MINUNITSIZE
36. }MEMORYPOOL, *PMEMORYPOOL;
37. /************************************************************************/
38. /* 生成内存池
39. * pBuf: 给定的内存buffer起始地址
40. * sBufSize: 给定的内存buffer大小
41. * 返回生成的内存池指针
42. /************************************************************************/
43. PMEMORYPOOL CreateMemoryPool(void* pBuf, size_t sBufSize);
44. /************************************************************************/
45. /* 暂时没用
46. /************************************************************************/
47. void ReleaseMemoryPool(PMEMORYPOOL* ppMem) ;
48. /************************************************************************/
49. /* 从内存池中分配指定大小的内存
50. * pMem: 内存池 指针
51. * sMemorySize: 要分配的内存大小
52. * 成功时返回分配的内存起始地址,失败返回NULL
53. /************************************************************************/
54. void* GetMemory(size_t sMemorySize, PMEMORYPOOL pMem) ;
55. /************************************************************************/
56. /* 从内存池中释放申请到的内存
57. * pMem:内存池指针
58. * ptrMemoryBlock:申请到的内存起始地址
59. /************************************************************************/
60. void FreeMemory(void *ptrMemoryBlock, PMEMORYPOOL pMem) ;
61. #endif //_MEMORYPOOL_H
/shawngucas/article/details/657486320/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
[cpp]
01. #include
02. #include "MemoryPool.h"
03. /************************************************************************/
04. /* 以下为大顶堆操作*/
05. void init_max_heap(size_t max_heap_size, memory_chunk* heap_arr, max_heap* heap)
06. {
07. heap‐>maxSize = max_heap_size;
08. heap‐>currentSize = 0;
09. heap‐>heap = heap_arr;
10. }
11. bool is_heap_empty(max_heap* heap)
12. {
13. return heap‐>currentSize == 0;
14. }
15. bool is_heap_full(max_heap* heap)
16. {
17. return heap‐>currentSize == heap‐>maxSize;
18. }
19. memory_chunk* filter_up(max_heap* heap, size_t start)
20. {
21. size_t i = start;
22. size_t j = ( i ‐ 1 ) / 2;
23. memory_chunk temp = heap‐>heap[i];
24. while(i > 0)
25. {
26. if(_size <= heap‐>heap[j].chunk_size)
27. break;
28. else
29. {
30. heap‐>heap[i] = heap‐>heap[j];
31. heap‐>heap[j].pfree_mem_addr‐>pmem_chunk = &(heap‐>heap[i]);
32. i = j;
33. j = (i ‐ 1) / 2;
34. }
35. }
36. heap‐>heap[i] = temp;
37. return &(heap‐>heap[i]);
38. }
39. memory_chunk* filter_down(max_heap* heap, size_t start, size_t endOfHeap)
40. {
41. size_t i = start;
42. size_t j = i * 2 + 1;
43. memory_chunk temp = heap‐>heap[i];
44. while(j <= endOfHeap)
45. {
46. if(j < endOfHeap && heap‐>heap[j].chunk_size < heap‐>heap[j+1].chunk_size)
47. j++;
48. if(_size > heap‐>heap[j].chunk_size)
49. break;
50. else
51. {
52. heap‐>heap[i] = heap‐>heap[j];
53. heap‐>heap[j].pfree_mem_addr‐>pmem_chunk = &(heap‐>heap[i]);
54. i = j;
55. j = 2 * i + 1;
56. }
57. }
58. heap‐>heap[i] = temp;
59. return &(heap‐>heap[i]);
60. }
61. memory_chunk* insert_heap(memory_chunk& chunk, max_heap* heap)
62. {
63. if (is_heap_full(heap))
64. {
65. return NULL;
66. }
67. heap‐>heap[heap‐>currentSize] = chunk;
68. memory_chunk* ret = filter_up(heap, heap‐>currentSize);
69. heap‐>currentSize++;
70. return ret;
71. }
72. bool get_max(memory_chunk*& chunk, max_heap* heap)
73. {
74. if(is_heap_empty(heap))
75. {
76. return false;
77. }
78. chunk = heap‐>heap;
79. return true;
80. }
81. bool remove_max(max_heap* heap)
82. {
83. if(is_heap_empty(heap))
84. {
85. return false;
/shawngucas/article/details/657486321/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
86. }
87. heap‐>heap[0] = heap‐>heap[heap‐>currentSize ‐ 1];
88. heap‐>currentSize‐‐;
89. if (heap‐>currentSize > 0)
90. {
91. filter_down(heap, 0, heap‐>currentSize‐1);
92. }
93. return true;
94. }
95. void remove_element(memory_chunk* chunk, max_heap* heap)
96. {
97. // 删除某个非max元素有两步组成:
98. // 1. 将该元素size增至最大(大于max element),然后将其上移至堆顶;
99. // 2. 删除堆顶元素
100. size_t index = chunk ‐ heap‐>heap;
101. chunk‐>chunk_size = MAXCHUNKSIZE;
102. filter_up(heap, index);
103. remove_max(heap);
104. }
105. memory_chunk* increase_element_value(memory_chunk* chunk, max_heap* heap, size_t increase_value)
106. {
107. size_t index = chunk ‐ heap‐>heap;
108. chunk‐>chunk_size += increase_value;
109. return filter_up(heap, index);
110. }
111. memory_chunk* decrease_element_value(memory_chunk* chunk, max_heap* heap, size_t decrease_value)
112. {
113. size_t index = chunk ‐ heap‐>heap;
114. chunk‐>chunk_size ‐= decrease_value;
115. return filter_down(heap, index, heap‐>currentSize‐1);
116. }
117. /************************************************************************/
118. /* 内存池起始地址对齐到ADDR_ALIGN字节
119. /************************************************************************/
120. size_t check_align_addr(void*& pBuf)
121. {
122. size_t align = 0;
123. size_t addr = (int)pBuf;
124. align = (ADDR_ALIGN ‐ addr % ADDR_ALIGN) % ADDR_ALIGN;
125. pBuf = (char*)pBuf + align;
126. return align;
127. }
128. /************************************************************************/
129. /* 内存block大小对齐到MINUNITSIZE字节
130. /************************************************************************/
131. size_t check_align_block(size_t size)
132. {
133. size_t align = size % MINUNITSIZE;
134.
135. return size ‐ align;
136. }
137. /************************************************************************/
138. /* 分配内存大小对齐到SIZE_ALIGN字节
139. /************************************************************************/
140. size_t check_align_size(size_t size)
141. {
142. size = (size + SIZE_ALIGN ‐ 1) / SIZE_ALIGN * SIZE_ALIGN;
143. return size;
144. }
145. /************************************************************************/
146. /* 内存映射表中的索引转化为内存起始地
址
147. /************************************************************************/
148. void* index2addr(PMEMORYPOOL mem_pool, size_t index)
149. {
150. char* p = (char*)(mem_pool‐>memory);
151. void* ret = (void*)(p + index *MINUNITSIZE);
152.
153. return ret;
154. }
155. /************************************************************************/
156. /* 内存起始地址转化为内存映射表中的索
引
157. /************************************************************************/
158. size_t addr2index(PMEMORYPOOL mem_pool, void* addr)
159. {
160. char* start = (char*)(mem_pool‐>memory);
161. char* p = (char*)addr;
162. size_t index = (p ‐ start) / MINUNITSIZE;
163. return index;
164. }
165. /************************************************************************/
166. /* 生成内存池
167. * pBuf: 给定的内存buffer起始地址
168. * sBufSize: 给定的内存buffer大小
169. * 返回生成的内存池指针
170. /************************************************************************/
/shawngucas/article/details/657486322/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
171. PMEMORYPOOL CreateMemoryPool(void* pBuf, size_t sBufSize)
172. {
173. memset(pBuf, 0, sBufSize);
174. PMEMORYPOOL mem_pool = (PMEMORYPOOL)pBuf;
175. // 计算需要多少memory map单元格
176. size_t mem_pool_struct_size = sizeof(MEMORYPOOL);
177. mem_pool‐
>mem_map_unit_count = (sBufSize ‐ mem_pool_struct_size + MINUNITSIZE ‐ 1) / MINUNITSIZE;
178. mem_pool‐>pmem_map = (memory_block*)((char*)pBuf + mem_pool_struct_size);
179. size_t max_heap_size = (sBufSize ‐ mem_pool_struct_size + MINUNITSIZE ‐ 1) / MINUNITSIZE;
180. memory_chunk* heap_arr = (memory_chunk*)
((char*)pBuf + mem_pool_struct_size + sizeof(memory_block) * mem_pool‐>mem_map_unit_count);
181.
182. mem_pool‐>memory = (char*)pBuf + mem_pool_struct_size+ sizeof(memory_block) * mem_pool‐
>mem_map_unit_count + sizeof(memory_chunk) * max_heap_size;
183. mem_pool‐>size = sBufSize ‐ mem_pool_struct_size ‐ sizeof(memory_block) * mem_pool‐
>mem_map_unit_count ‐ sizeof(memory_chunk) * max_heap_size;
184. size_t align = check_align_addr(mem_pool‐>memory);
185. mem_pool‐>size ‐= align;
186. mem_pool‐>size = check_align_block(mem_pool‐>size);
187. mem_pool‐>mem_block_count = mem_pool‐>size / MINUNITSIZE;
188. init_max_heap(mem_pool‐>mem_block_count, heap_arr, &(mem_pool‐>heap));
189. memory_chunk chunk;
190. _size = mem_pool‐>mem_block_count;
191. memory_chunk* pos = insert_heap(chunk, &(mem_pool‐>heap));
192.
193. // 初始化 pmem_map
194. mem_pool‐>pmem_map[0].count = mem_pool‐>mem_block_count;
195. mem_pool‐>pmem_map[0].pmem_chunk = pos;
196. mem_pool‐>pmem_map[mem_pool‐>mem_block_count‐1].start = 0;
197.
198. pos‐>pfree_mem_addr = mem_pool‐>pmem_map;
199. mem_pool‐>mem_used_size = 0;
200. return mem_pool;
201. }
202. /************************************************************************/
203. /* 暂时没用
204. /************************************************************************/
205. void ReleaseMemoryPool(PMEMORYPOOL* ppMem)
206. {
207. }
208. /************************************************************************/
209. /* 从内存池中分配指定大小的内存
210. * pMem: 内存池 指针
211. * sMemorySize: 要分配的内存大小
212. * 成功时返回分配的内存起始地址,失败返回NULL
213. /************************************************************************/
214. void* GetMemory(size_t sMemorySize, PMEMORYPOOL pMem)
215. {
216. sMemorySize = check_align_size(sMemorySize);
217. size_t index = 0;
218. memory_chunk* max_chunk;
219. bool ret = get_max(max_chunk, &(pMem‐>heap));
220. if (ret == false || max_chunk‐>chunk_size * MINUNITSIZE < sMemorySize)
221. {
222. return NULL;
223. }
224. pMem‐>mem_used_size += sMemorySize;
225. if (max_chunk‐>chunk_size * MINUNITSIZE == sMemorySize)
226. {
227. // 当要分配的内存大小与当前chunk中的内存大小相同时,从pfree_mem_chunk链表中删除此chunk
228. size_t current_index = (max_chunk‐>pfree_mem_addr ‐ pMem‐>pmem_map);
229. remove_max(&(pMem‐>heap));
230.
231. return index2addr(pMem, current_index);
232. }
233. else
234. {
235. // 当要分配的内存小于当前chunk中的内存时,更改pfree_mem_chunk中相应chunk的pfree_mem_addr
236.
237. // 复制当前mem_map_unit
238. memory_block copy;
239. = max_chunk‐>pfree_mem_addr‐>count;
240. _chunk = max_chunk;
241. // 记录该block的起始和结束索引
242. memory_block* current_block = max_chunk‐>pfree_mem_addr;
243. current_block‐>count = sMemorySize / MINUNITSIZE;
244. size_t current_index = (current_block ‐ pMem‐>pmem_map);
245. pMem‐>pmem_map[current_index+current_block‐>count‐1].start = current_index;
246. current_block‐>pmem_chunk = NULL; // NULL表示当前内存块已被分配
247. // 当前block被一分为二,更新第二个block中的内容
248. memory_chunk* pos = decrease_element_value(max_chunk, &(pMem‐>heap), current_block‐
>count);
249. pMem‐>pmem_map[current_index+current_block‐>count].count = ‐ current_block‐
>count;
250. pMem‐>pmem_map[current_index+current_block‐>count].pmem_chunk = pos;
251. // 更新原来的pfree_mem_addr
/shawngucas/article/details/657486323/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
252. pos‐>pfree_mem_addr = &(pMem‐>pmem_map[current_index+current_block‐>count]);
253.
254. size_t end_index = current_index + ‐ 1;
255. pMem‐>pmem_map[end_index].start = current_index + current_block‐>count;
256. return index2addr(pMem, current_index);
257. }
258. }
259. /************************************************************************/
260. /* 从内存池中释放申请到的内存
261. * pMem:内存池指针
262. * ptrMemoryBlock:申请到的内存起始地址
263. /************************************************************************/
264. void FreeMemory(void *ptrMemoryBlock, PMEMORYPOOL pMem)
265. {
266. size_t current_index = addr2index(pMem, ptrMemoryBlock);
267. size_t size = pMem‐>pmem_map[current_index].count * MINUNITSIZE;
268. // 判断与当前释放的内存块相邻的内存块是否可以与当前释放的内存块合并
269. memory_block* pre_block = NULL;
270. memory_block* next_block = NULL;
271. memory_block* current_block = &(pMem‐>pmem_map[current_index]);
272. // 第一个
273. if (current_index == 0)
274. {
275. if (current_block‐>count < pMem‐>mem_block_count)
276. {
277. next_block = &(pMem‐>pmem_map[current_index+current_block‐>count]);
278. // 如果后一个内存块是空闲的,合并
279. if (next_block‐>pmem_chunk != NULL)
280. {
281. memory_chunk* pos = increase_element_value(next_block‐>pmem_chunk, &(pMem‐
>heap), current_block‐>count);
282. pos‐>pfree_mem_addr = current_block;
283. pMem‐>pmem_map[current_index+current_block‐>count+next_block‐>count‐
1].start = current_index;
284. current_block‐>count += next_block‐>count;
285. current_block‐>pmem_chunk = pos;
286. next_block‐>pmem_chunk = NULL;
287. }
288. // 如果后一块内存不是空闲的,在pfree_mem_chunk中增加一个chunk
289. else
290. {
291. memory_chunk new_chunk;
292. new__size = current_block‐>count;
293. new__mem_addr = current_block;
294. memory_chunk* pos = insert_heap(new_chunk, &(pMem‐>heap));
295. current_block‐>pmem_chunk = pos;
296. }
297. }
298. else
299. {
300. memory_chunk new_chunk;
301. new__size = current_block‐>count;
302. new__mem_addr = current_block;
303. memory_chunk* pos = insert_heap(new_chunk, &(pMem‐>heap));
304. current_block‐>pmem_chunk = pos;
305. }
306. }
307.
308. // 最后一个
309. else if (current_index == pMem‐>mem_block_count‐1)
310. {
311. if (current_block‐>count < pMem‐>mem_block_count)
312. {
313. pre_block = &(pMem‐>pmem_map[current_index‐1]);
314. size_t index = pre_block‐>count;
315. pre_block = &(pMem‐>pmem_map[index]);
316.
317. // 如果前一个内存块是空闲的,合并
318. if (pre_block‐>pmem_chunk != NULL)
319. {
320. memory_chunk* pos = increase_element_value(pre_block‐>pmem_chunk, &(pMem‐
>heap), current_block‐>count);
321. pre_block‐>pmem_chunk = pos;
322. pMem‐>pmem_map[current_index+current_block‐>count‐
1].start = current_index ‐ pre_block‐>count;
323. pre_block‐>count += current_block‐>count;
324. current_block‐>pmem_chunk = NULL;
325. }
326. // 如果前一块内存不是空闲的,在pfree_mem_chunk中增加一个chunk
327. else
328. {
329. memory_chunk new_chunk;
330. new__size = current_block‐>count;
331. new__mem_addr = current_block;
332. memory_chunk* pos = insert_heap(new_chunk, &(pMem‐>heap));
333. current_block‐>pmem_chunk = pos;
334. }
/shawngucas/article/details/657486324/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
335. }
336. else
337. {
338. memory_chunk new_chunk;
339. new__size = current_block‐>count;
340. new__mem_addr = current_block;
341. memory_chunk* pos = insert_heap(new_chunk, &(pMem‐>heap));
342. current_block‐>pmem_chunk = pos;
343. }
344. }
345. else
346. {
347. next_block = &(pMem‐>pmem_map[current_index+current_block‐>count]);
348. pre_block = &(pMem‐>pmem_map[current_index‐1]);
349. size_t index = pre_block‐>start;
350. pre_block = &(pMem‐>pmem_map[index]);
351. bool is_back_merge = false;
352. if (next_block‐>pmem_chunk == NULL && pre_block‐>pmem_chunk == NULL)
353. {
354. memory_chunk new_chunk;
355. new__size = current_block‐>count;
356. new__mem_addr = current_block;
357. memory_chunk* pos = insert_heap(new_chunk, &(pMem‐>heap));
358. current_block‐>pmem_chunk = pos;
359. }
360. // 后一个内存块
361. if (next_block‐>pmem_chunk != NULL)
362. {
363. memory_chunk* pos = increase_element_value(next_block‐>pmem_chunk, &(pMem‐
>heap), current_block‐>count);
364. pos‐>pfree_mem_addr = current_block;
365. pMem‐>pmem_map[current_index+current_block‐>count+next_block‐>count‐
1].start = current_index;
366. current_block‐>count += next_block‐>count;
367. current_block‐>pmem_chunk = pos;
368. next_block‐>pmem_chunk = NULL;
369. is_back_merge = true;
370. }
371. // 前一个内存块
372. if (pre_block‐>pmem_chunk != NULL)
373. {
374. pMem‐>pmem_map[current_index+current_block‐>count‐
1].start = current_index ‐ pre_block‐>count;
375. pre_block‐>count += current_block‐>count;
376. memory_chunk* pos = increase_element_value(pre_block‐>pmem_chunk, &(pMem‐
>heap), current_block‐>count);
377. pre_block‐>pmem_chunk = pos;
378. pos‐>pfree_mem_addr = pre_block;
379. if (is_back_merge)
380. {
381. remove_element(current_block‐>pmem_chunk, &(pMem‐>heap));
382. }
383. current_block‐>pmem_chunk = NULL;
384. }
385. }
386. pMem‐>mem_used_size ‐= size;
387. }
[cpp]
01. // memory pool : Defines the entry point for the console application.
02. //
03. #include
04. #include "MemoryPool.h"
05. #include
06. #include
07. #include
08. #include
09. #include
10. #include
11. using namespace std;
12. int break_time = 0;
13. size_t used_size = 0;
14. void output_heap(max_heap* heap, ofstream& out)
15. {
16. for (int k = 0; k < heap‐>currentSize; k++)
17. {
18. if (k != 0 && k % 10 == 0)
19. {
20. out << endl;
21. }
/shawngucas/article/details/657486325/32
4/28/2015
22.
23.
24.
25.
26.
内存池设计与实现 shawn的专栏 博客频道
out << heap‐>heap[k].chunk_size << " ";
}
out << endl;
}
void check_mem_pool(int& max_chunk_size, int& free_chunk_count, int& min_chunk_size, int& total_free_mem, MEMORYPOOL* m
27. {
28. total_free_mem = 0;
29. max_chunk_size = 0;
30. min_chunk_size = 1024*1024*1024;
31. free_chunk_count = mem_pool‐>tSize;
32.
33. size_t size;
34. for (int k = 0; k < free_chunk_count; k++)
35. {
36. size = mem_pool‐>[k].chunk_size * MINUNITSIZE;
37. total_free_mem += size;
38. if (size > max_chunk_size)
39. {
40. max_chunk_size = size;
41. }
42. if (size < min_chunk_size)
43. {
44. min_chunk_size = size;
45. }
46. }
47. }
48. // 申请后紧接着释放
49. double test_mem_pool_perf_1(PMEMORYPOOL mem_pool, int iter, int* sizes)
50. {
51. cout << "*********************test_mem_pool_perf_1*********************" << endl;
52. LARGE_INTEGER litmp;
53. LONGLONG QPart1, QPart2;
54. double t;
55. double dfMinus, dfFreq;
56. QueryPerformanceFrequency(&litmp);
57. dfFreq = (double)rt;// 获得计数器的时钟频率
58. QueryPerformanceCounter(&litmp);
59. QPart1 = rt;// 获得初始值
60. for (int i = 0; i < iter; i++)
61. {
62. void *p = GetMemory(sizes[i], mem_pool);
63. if (p == NULL)
64. {
65. cout << "break @ iterator = " << i << " / " << iter << ", need memory " << sizes[i] <<
66. cout << "total memory is: " << mem_pool‐>size << " Byte" << endl;
67. cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl;
68. cout << "memory left is: " << mem_pool‐>size ‐ mem_pool‐
>mem_used_size << endl << endl;
69. int max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem;
70. check_mem_pool(max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem, mem_pool);
71. cout << "check memory pool result:" << endl;
72. cout << "free_chunk_count: " << free_chunk_count << endl
73. << "total_free_mem: " << total_free_mem << endl
74. << "max_chunk_size: " << max_chunk_size << endl
75. << "min_chunk_size: " << min_chunk_size << endl;
76. break;
77. }
78. FreeMemory(p, mem_pool);
79. }
80. QueryPerformanceCounter(&litmp);
81. QPart2 = rt;//获得中止值
82. dfMinus = (double)(QPart2‐QPart1);
83. t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
84. cout << "test_mem_pool_perf_1: iter = " << iter << endl;
85. cout << "time: " << t << endl;
86. cout << "*********************test_mem_pool_perf_1*********************" << endl << endl << endl;
87. return t;
88. }
89. double test_std_perf_1(int iter, int* sizes)
90. {
91. cout << "*********************test_std_perf_1*********************" << endl;
92. LARGE_INTEGER litmp;
93. LONGLONG QPart1, QPart2;
94. double t;
95. double dfMinus, dfFreq;
96. QueryPerformanceFrequency(&litmp);
97. dfFreq = (double)rt;// 获得计数器的时钟频率
98. QueryPerformanceCounter(&litmp);
99. QPart1 = rt;// 获得初始值
100. for (int i = 0; i < iter; i++)
101. {
102. void *p = malloc(sizes[i]);
103. if (p == NULL)
104. {
105. cout << "break @ iterator = " << i << " / " << iter << ", need memory " << sizes[i] <<
106. break;
107. }
/shawngucas/article/details/657486326/32
4/28/2015
108.
109.
110.
111.
112.
113.
114.
115.
116.
内存池设计与实现 shawn的专栏 博客频道
free(p);
}
QueryPerformanceCounter(&litmp);
QPart2 = rt;//获得中止值
dfMinus = (double)(QPart2‐QPart1);
t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
cout << "test_std_perf_1: iter = " << iter << endl;
cout << "time: " << t << endl;
cout << "*********************test_std_perf_1*********************" << endl << endl << endl;
117. return t;
118. }
119. double test_mem_pool_perf_rand(PMEMORYPOOL mem_pool, int iter, int* sizes, int* instruction)
120. {
121. cout << "‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐test_mem_pool_perf_rand‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ "<< endl;
122. void** p = new void*[iter];
123. if (p == NULL)
124. {
125. cout << "new failed" << endl;
126. return ‐1;
127. }
128. cout << "test start" << endl;
129. LARGE_INTEGER litmp, gftime;
130. LONGLONG QPart1, QPart2, start, finish;
131. double t, GetMemory_time, FreeMemory_time;
132. double dfMinus, dfFreq;
133. QueryPerformanceFrequency(&litmp);
134. dfFreq = (double)rt;// 获得计数器的时钟频率
135. QueryPerformanceCounter(&litmp);
136. QPart1 = rt;// 获得初始值
137. int index = 0;
138. int size;
139. int free_tmp = 0;
140. double seach_time;
141. for (int i = 0; i < iter; i++)
142. {
143. size = sizes[i];
144. p[index++] = GetMemory(size, mem_pool);
145. if (p[index‐1] == NULL)
146. {
147. break_time++;
148. cout << "break @ iterator = " << i << " / " << iter << ", need memory " << size <<
149. cout << "total memory is: " << mem_pool‐>size << " Byte" << endl;
150. cout << "memory used is: " << mem_pool‐>mem_used_size << " Byte" << endl;
151. cout << "memory left is: " << mem_pool‐>size ‐ mem_pool‐
>mem_used_size << endl << endl;
152. int max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem;
153. check_mem_pool(max_chunk_size, free_chunk_count, min_chunk_size, total_free_mem, mem_pool);
154. cout << "check memory pool result:" << endl;
155. cout << "free_chunk_count: " << free_chunk_count << endl
156. << "total_free_mem: " << total_free_mem << endl
157. << "max_chunk_size: " << max_chunk_size << endl
158. << "min_chunk_size: " << min_chunk_size << endl;
159. break;
160. }
161. used_size += size;
162. if (instruction[i] == 1)
163. {
164. FreeMemory(p[‐‐index], mem_pool);
165. used_size ‐= size;
166. }
167. }
168.
169. QueryPerformanceCounter(&litmp);
170. QPart2 = rt;//获得中止值
171. dfMinus = (double)(QPart2‐QPart1);
172. t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
173. cout << "test_mem_pool_perf_rand: iter = " << iter << endl;
174. cout << "time: " << t << endl << endl;
175. delete []p;
176. return t;
177. }
178. double test_std_perf(int iter, int* sizes, int* instruction)
179. {
180. cout << "test_std_perf" << endl;
181. void** p =new void*[iter];
182. if (p == NULL)
183. {
184. cout << "new failed" << endl;
185. return ‐1;
186. }
187.
188. LARGE_INTEGER litmp;
189. LONGLONG QPart1, QPart2;
190. double t;
191. double dfMinus, dfFreq;
192. QueryPerformanceFrequency(&litmp);
193. dfFreq = (double)rt;// 获得计数器的时钟频率
/shawngucas/article/details/657486327/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
194. QueryPerformanceCounter(&litmp);
195. QPart1 = rt;// 获得初始值
196. // cout << "test start" << endl;
197. int index = 0;
198. int size;
199. for (int i = 0; i < iter; i++)
200. {
201. size = sizes[i];
202. p[index++] = malloc(size);
203. if (p[index‐1] == NULL)
204. {
205. cout << i << endl;
206. break;
207. }
208. if (instruction[i] == 1)
209. {
210. free(p[‐‐index]);
211. }
212. }
213. QueryPerformanceCounter(&litmp);
214. QPart2 = rt;//获得中止值
215. dfMinus = (double)(QPart2‐QPart1);
216. t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
217. cout << "test_std_perf: iter = " << iter << endl;
218. cout << "time: " << t << endl << endl;
219. for (int k = 0; k < index; k++)
220. {
221. free(p[k]);
222. }
223. return t;
224. }
225. double test_std_perf_fix_size(int iter, int size)
226. {
227. cout << "test_std_perf_fix_size" << endl;
228. LARGE_INTEGER litmp;
229. LONGLONG QPart1, QPart2;
230. double t;
231. double dfMinus, dfFreq;
232. QueryPerformanceFrequency(&litmp);
233. dfFreq = (double)rt;// 获得计数器的时钟频率
234. QueryPerformanceCounter(&litmp);
235. QPart1 = rt;// 获得初始值
236. int index = 0;
237.
238. for (int i = 0; i < iter; i++)
239. {
240. void *p = malloc(size);
241. if (p == NULL)
242. {
243. cout << i << endl;
244. break;
245. }
246. free(p);
247. }
248. QueryPerformanceCounter(&litmp);
249. QPart2 = rt;//获得中止值
250. dfMinus = (double)(QPart2‐QPart1);
251. t = dfMinus / dfFreq;// 获得对应的时间值,单位为秒
252. cout << "test_std_perf: iter = " << iter << endl;
253. cout << "time: " << t << endl << endl;
254. return t;
255. }
256. void rand_test()
257. {
258. ofstream out("rand_");
259. used_size = 0;
260. int iter = 2000;
261. size_t sBufSize = 500* 1024*1024;
262. void*pBuf = malloc(sBufSize);
263. if (pBuf == NULL)
264. {
265. cout << "malloc failed" << endl;
266. return;
267. }
268. PMEMORYPOOL mem_pool = CreateMemoryPool(pBuf, sBufSize);
269. int* instruction = new int[iter];
270. int* sizes = new int[iter];
271. if (instruction == NULL || sizes == NULL)
272. {
273. cout << "new failed" << endl;
274. return;
275. }
276. srand(time(NULL));
277. ofstream out_rand("rand");
278. ofstream out_size("size");
279. cout << "generate rand number" << endl;
280. int k_count = 0;
/shawngucas/article/details/657486328/32
4/28/2015
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
内存池设计与实现 shawn的专栏 博客频道
for (int i = 0; i < iter; i++)
{
instruction[i] = rand() % 2;
sizes[i] = (rand() % 16 + 1) * 64;
}
int test_count = 200;
double t1, t2;
double* ratio = new double[test_count];
int count = 0;
for (int k = 0; k < test_count; k++)
{
if (break_time != 0)
{
cout << "break @ " << k << " / " << test_count << endl;
break;
}
count++;
cout << "******************************************test " << k+1 << " *****************************************
299. t1 = test_std_perf(iter, sizes, instruction);
300. t2 = test_mem_pool_perf_rand(mem_pool, iter, sizes, instruction);
301. cout << "total memory: " << mem_pool‐>size << ", memory used: " << mem_pool‐
>mem_used_size
302. << ", memory left: " << mem_pool‐>size ‐ mem_pool‐>mem_used_size << endl;
303. ratio[k] = t1 / t2;
304. }
305. if(break_time == 0)
306. break_time = test_count;
307. break_time = count ‐ 1;
308. cout << "*************************** ratio (system time / mem_pool time) ***************************"
309. for (int k = 0; k < break_time; k++)
310. {
311. out << ratio[k] << ",";
312. if (k % 10 == 0 && k != 0)
313. {
314. cout << endl;
315. }
316. cout << ratio[k] << " ";
317. }
318. cout << endl;
319. delete []ratio;
320. free(pBuf);
321. delete []instruction;
322. delete []sizes;
323. }
324. // 申请紧接着释放
325. void rand_test_2()
326. {
327. size_t sBufSize = 500* 1024*1024;
328. void*pBuf = malloc(sBufSize);
329. if (pBuf == NULL)
330. {
331. cout << "malloc failed" << endl;
332. return;
333. }
334. PMEMORYPOOL mem_pool = CreateMemoryPool(pBuf, sBufSize);
335. int iter = 1000;
336. int test_count = 1024;
337. int* sizes = new int[iter];
338. double* ratio = new double[test_count];
339. double* std_perf = new double[test_count];
340. double* mem_pool_perf = new double[test_count];
341. if (sizes == NULL || ratio == NULL)
342. {
343. cout << "new memory failed" << endl;
344. return;
345. }
346. srand(time(NULL));
347. cout << "generate rand number" << endl;
348. ofstream out("rand_test_");
349. ofstream out_std("std_perf_");
350. ofstream out_mem_pool("mem_pool_perf_");
351. for (int k = 0; k < test_count; k++)
352. {
353. for (int i = 0; i < iter; i++)
354. {
355. sizes[i] = (rand() % 16 + 1) * 64 + 1024 * k;
356. }
357. cout << "******************************************test " << k+1 << " *****************************************
358. double mem_pool_t = test_mem_pool_perf_1(mem_pool, iter, sizes);
359. double std_t = test_std_perf_1(iter, sizes);
360. std_perf[k] = std_t;
361. mem_pool_perf[k] = mem_pool_t;
362. ratio[k] = std_t / mem_pool_t;
363. }
364. cout << "*************************** ratio (system time / mem_pool time) ***************************"
365. for (int k = 0; k < test_count; k++)
366. {
/shawngucas/article/details/657486329/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
367. out_std << std_perf[k] << ",";
368. out_mem_pool << mem_pool_perf[k] << ",";
369. out << ratio[k] << ",";
370. if (k % 10 == 0 && k != 0)
371. {
372. cout << endl;
373. }
374. cout << ratio[k] << " ";
375. }
376. cout << endl;
377. delete []sizes;
378. delete []ratio;
379. delete []mem_pool_perf;
380. delete []std_perf;
381. free(pBuf);
382. }
383. int _tmain(int argc, _TCHAR* argv[])
384. {
385. // rand_test();
386. rand_test_2();
387.
388. return 0;
389. }
下一篇关于lib和dll
顶踩
160
主题推荐
设计内存数据结构内存管理c语言
猜你在找
C++学习之深入理解虚函数--虚函数表解析【精品课程】竟有如此全面的软考资料?“碉堡”了!
手把手实现红黑树【精品课程】HTML 5全掌控
string的size和length【精品课程】Cocos2d-x实战-手把手教你上线项目-迷失
CC++2014年7月华为校招机试真题一【精品课程】Swift语言进阶
KMP算法原理与实现精简【精品课程】深入浅出MySQL入门必备
准备好了么? !
跳
吧
更多职位尽在 CSDN JOB
UI设计/美工
我要跳槽
UI视觉设计总监
我要跳槽
重庆荆棘鸟科技有限公司|5-8K/月北京约拍啦网络科技有限公司|15-20K/月
移动端设计
我要跳槽
Web网页前端设计
我要跳槽
青岛易航线网络科技有限公司|6-7K/月台州市盛世伟业网络技术有限公司|3-5K/月
查看评论
16楼 erxiaodao 20150403 12:25发表
好文章!
请教下,性能测试结果图是用什么工具画的?
15楼 tifentan 20141209 16:25发表
假设输入500M的内存被管理的结构吃了100多M?
不太科学啊。
/shawngucas/article/details/657486330/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
14楼 it_child 20140508 16:04发表
或者说315行的
size_t index = pre_block>count;
应该改成
size_t index = pre_block>start;
楼主求解释啊
13楼 it_child 20140508 15:59发表
void FreeMemory(void *ptrMemoryBlock, PMEMORYPOOL pMem) 函数中的
309. // 最后一个
310. else if (current_index == pMem>mem_block_count1)
311. {
312. if (current_block>count < pMem>mem_block_count)
313. {
314. pre_block = &(pMem>pmem_map[current_index1]);
315. size_t index = pre_block>count;
316. pre_block = &(pMem>pmem_map[index]);
317.
318. // 如果前一个内存块是空闲的,合并
请问第316行是不是有问题啊
12楼 樱花树樱花开 20140426 18:24发表
今天刚刚学了 操作系统中的 内存管理...~我怎么就没想到 把操作系统中的这种内存管理来这样使用呢~~
11楼 cyxHehui 20131123 09:03发表
hi,mem_map_pool_count和mem_map_unit_count分别是什么呀?你在createMemoryPool的时候这两个的赋值是不是弄错了
呀
10楼 whdugh 20131005 21:56发表
膜拜楼主 牛比
9楼 高鹏0071 20130829 10:15发表
整理这么多,辛苦楼主了啊。
8楼 头头 20130609 13:01发表
当然我是在多线程下面测试的,我对两个分配函数有座同步处理
7楼 头头 20130609 10:48发表
楼主,你这个有重大bug,当连续分配2 块以上的内存的时候,然后再来释放,就内存泄露,bug了
6楼 uia0702 20130530 21:48发表
绝对的好资料……,你可以当老师了,无私啊
5楼 eagleatustb 20120927 14:22发表
我想探讨两个问题:
[cpp]
01.
02.
03.
04.
05.
06.
07.
08.
09.
10.
11.
12.
13.
14.
15.
16.
/************************************************************************/
/* 内存block大小对齐到MINUNITSIZE字节
/************************************************************************/
size_t check_align_block(size_t size)
{
size_t align = size % MINUNITSIZE;
return size ‐ align;
}
/************************************************************************/
/* 分配内存大小对齐到SIZE_ALIGN字节
/************************************************************************/
size_t check_align_size(size_t size)
{
size = (size + SIZE_ALIGN ‐ 1) / SIZE_ALIGN * SIZE_ALIGN;
return size;
}
1.上面两个对齐好像不一致,check_align_block应该是向下对齐,即如果size = 32 < MINUNITSIZE,输出是0;而
check_align_size是向上对齐的,即如果size = 32 < SIZE_ALIGN,输出是1;这同一个系列的函数,不同的对齐方式,是出于
什么考虑,能说明一下吗?
2.另外,对于向上或向下对齐实现方式,我觉得应该使用位运算去处理,因为根据你的理论,这毕竟是为了提高效率而作的设
计。size = (size + SIZE_ALIGN 1) / SIZE_ALIGN * SIZE_ALIGN; 如果使用 return (size+SIZE_ALIGN1)&~(SIZE_ALIGN1)
来实现,应该会相对高效一点。
/shawngucas/article/details/657486331/32
4/28/2015内存池设计与实现 shawn的专栏 博客频道
4楼 scdxmoe 20120831 16:03发表
牛逼
3楼 彭家老三 20120222 19:29发表
多谢博主,二楼你真懒...
2楼 heguijiss 20120209 17:13发表
学习了!
能否将整个源码打包呢?我的邮箱:heguijiss@.谢谢!
1楼 wangbin6857 20111207 10:06发表
good
您还没有登录,请[登录]或[注册]
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
核心技术类目
全部主题
VPN
BI
FTC
Angular
Hadoop
ERP
Spring
UML
AWS
IE10
移动游戏
Eclipse
.NET
Java
CRM
API
云计算
Tornado
Django
Android
JavaScript
HTML
Rails
iOS6
Ruby
iOS
SDK
Swift
IIS
智能硬件
Ubuntu
Fedora
KDE
Docker
WAP
LBS
OpenStack
jQuery
Unity
Maemo
Solr
Spark
HTML5
coremail
数据库
QEMU
Hibernate
NFC
XML Apache
Splashtop
Compuware
components
OPhone
aptech
Redis
Windows Mobile
Perl
Cassandra
HBase
CloudStack
Pure
CouchBase
Scala
Rackspace Web App
ThinkPHP
SpringSide
大数据
Cloud Foundry Bootstrap
公司简介
|
招贤纳士
|
广告服务
|
银行汇款帐号
|
联系方式
|
版权声明
|
法律顾问
|
问题报告
|
合作伙伴
|
论坛反馈
网站客服杂志客服微博客服webmaster@400-600-2320|北京创新乐知信息技术有限公司 版权所有|江苏乐知网络技术有限公司 提供商务支持
京 ICP 证 070598 号|Copyright © 1999-2014, , All Rights Reserved
/shawngucas/article/details/657486332/32
版权声明:本文标题:内存池设计与实现 - shawn的专栏 - 博客频道 - CSDN 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dongtai/1720791295a843114.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论