admin管理员组

文章数量:1567529

2024年7月12日发(作者:)

4/28/2015内存池设计与实现 ­ shawn的专栏 ­ 博客频道 ­

登录 | 注册

shawn的专栏

目录视图摘要视图订阅

个人资料

Markdown博文大赛清新开启 天天爱答题 一大波C币袭来 寻找Java大牛! 一次拿下软考,我自有锦囊妙计!

内存池设计与实现

分类: C/C++

2011­06­29 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. vectorvec;

400. vector::iterator vec_iter;

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 2015­04­03 12:25发表

好文章!

请教下,性能测试结果图是用什么工具画的?

15楼 tifentan 2014­12­09 16:25发表

假设输入500M的内存被管理的结构吃了100多M?

不太科学啊。

/shawngucas/article/details/657486330/32

4/28/2015内存池设计与实现 ­ shawn的专栏 ­ 博客频道 ­

14楼 it_child 2014­05­08 16:04发表

或者说315行的

size_t index = pre_block­>count;

应该改成

size_t index = pre_block­>start;

楼主求解释啊

13楼 it_child 2014­05­08 15:59发表

void FreeMemory(void *ptrMemoryBlock, PMEMORYPOOL pMem) 函数中的

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. // 如果前一个内存块是空闲的,合并

请问第316行是不是有问题啊

12楼 樱花树樱花开 2014­04­26 18:24发表

今天刚刚学了 操作系统中的 内存管理...~我怎么就没想到 把操作系统中的这种内存管理来这样使用呢~~

11楼 cyxHehui 2013­11­23 09:03发表

hi,mem_map_pool_count和mem_map_unit_count分别是什么呀?你在createMemoryPool的时候这两个的赋值是不是弄错了

10楼 whdugh 2013­10­05 21:56发表

膜拜楼主 牛比

9楼 高鹏0071 2013­08­29 10:15发表

整理这么多,辛苦楼主了啊。

8楼 头头 2013­06­09 13:01发表

当然我是在多线程下面测试的,我对两个分配函数有座同步处理

7楼 头头 2013­06­09 10:48发表

楼主,你这个有重大bug,当连续分配2 块以上的内存的时候,然后再来释放,就内存泄露,bug了

6楼 uia0702 2013­05­30 21:48发表

绝对的好资料……,你可以当老师了,无私啊

5楼 eagleatustb 2012­09­27 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_ALIGN­1)&~(SIZE_ALIGN­1)

来实现,应该会相对高效一点。

/shawngucas/article/details/657486331/32

4/28/2015内存池设计与实现 ­ shawn的专栏 ­ 博客频道 ­

4楼 scdxmoe 2012­08­31 16:03发表

牛逼

3楼 彭家老三 2012­02­22 19:29发表

多谢博主,二楼你真懒...

2楼 heguijiss 2012­02­09 17:13发表

学习了!

能否将整个源码打包呢?我的邮箱:heguijiss@.谢谢!

1楼 wangbin6857 2011­12­07 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

本文标签: 内存实现设计分配释放