efficient c++,单线程内存池
基于 http://www.cnblogs.com/diegodu/p/4555018.html operator new的知识基础上 介绍这个章节的内容
对于一般直接 new 与delete 性能较差,可以自己管理写内存的申请与释放。其实一般的operator new 和operator delete 直接调用 malloc 和 free的。
版本0:
class Rational
{
public:
Rational(int a=, int b = ): n(a),d(b){}
private:
int n;
int d;
};
版本1:专用的内存管理器
#include <stddef.h> // for size_t
#include <iostream> using namespace std; class NextOnFreeList {
public:
NextOnFreeList *next;
}; class Rational {
public:
Rational (int a = , int b = ) : n(a), d(b) {}
inline void *operator new(size_t size);
inline void operator delete(void *doomed, size_t size); static void newMemPool() { expandTheFreeList(); }
static void deleteMemPool(); private:
static NextOnFreeList *freeList; // A free list of Rational objects.
static void expandTheFreeList();
enum { EXPANSION_SIZE = }; int n; // Numerator
int d; // Denominator
}; inline
void * Rational::operator new(size_t size)
{
if ( == freeList) {// If the list is empty, fill it up.
expandTheFreeList();
} NextOnFreeList *head = freeList;
freeList = head->next; return head;
} inline
void Rational::operator delete(void *doomed, size_t size)
{
NextOnFreeList *head = static_cast <NextOnFreeList *> (doomed);
head->next = freeList;
freeList = head;
} void Rational::expandTheFreeList()
{
// We must allocate an object large enough to contain the next
// pointer.
size_t size = (sizeof(Rational) > sizeof(NextOnFreeList *)) ?
sizeof(Rational) : sizeof(NextOnFreeList *); // NextOnFreeList *runner = static_cast <NextOnFreeList *>(new char[size]);
NextOnFreeList *runner = (NextOnFreeList *)(new char[size]); freeList = runner;
for (int i = ; i < EXPANSION_SIZE; i++) {
//runner->next = static_cast <NextOnFreeList *> (new char[size]);
runner->next = (NextOnFreeList *)(new char[size]);
runner = runner->next;
} runner->next = ; cout << "expand" << endl;
} void Rational::deleteMemPool()
{
NextOnFreeList *nextPtr;
for (nextPtr = freeList; nextPtr != NULL; nextPtr = freeList) {
freeList = freeList->next;
delete [] nextPtr;
}
}
//测试code NextOnFreeList *Rational::freeList = ; int main()
{
Rational *array[]; Rational::newMemPool(); // Start timing here for (int j = ; j < ; j++) {
for (int i = ; i < ; i++) {
array[i] = new Rational(i);
}
for (int i = ; i < ; i++) {
delete array[i];
}
} // Stop timing here Rational::deleteMemPool(); return ;
}
这版本是通过重载 目标类 中的new 与delete 实现内存管理,只适用于目标类,但是速度是最快的。
实现方式是维护一个链表,类中静态声明链表头,链表维护一串空间,通过类型转换在 目标类 和 链表指针 之间转换。
如果内存不够(freelist=NULL)是一次申请较多内存进行维护。
链表的添加删除(对于函数释放空间与申请空间)是在链首操作。
书上47 行 52行通过 静态类型转换不成功,改为了 强制转换,在 g++ 中能够编译运行。
主要在主函数中调用静态函数 链表的申请与释放。
版本2:固定大小对象的内存池
考虑版本1,可以通过模板实现管理特定的对象。最主要的参数是类的大小。
实现是专门声明一个管理内存的内存池类,使用模板实现,提供alloc() free() 接口,给类申请与释放内存。
内存池类的实现是自身有一个MemoryPool<T>* next 指针用来指向维护的链表,内存的操作都在链首位置。
#include <stddef.h>
#include <iostream> using namespace std; template <class T>
class MemoryPool {
public:
MemoryPool (size_t size = EXPANSION_SIZE);
~MemoryPool (); // Allocate a T element from the free list.
inline void* alloc (size_t size); // Return a T element to the free list.
inline void free (void *someElement);
private:
// next element on the free list.
MemoryPool<T> *next; // If the freeList is empty, expand it by this amount.
enum { EXPANSION_SIZE = }; // Add free elements to the free list
void expandTheFreeList(int howMany = EXPANSION_SIZE);
}; template <class T>
MemoryPool <T> :: MemoryPool (size_t size)
{
expandTheFreeList(size);
} template < class T >
MemoryPool < T > :: ~MemoryPool ()
{
MemoryPool<T> *nextPtr = next;
for (nextPtr = next; nextPtr != NULL; nextPtr = next) {
next = next->next;
cout << nextPtr << endl;
//delete [] nextPtr;
//delete nextPtr;
delete [](char*)nextPtr; //不太明白为什么这样是对的,上面的方法不行。。
//明白了,因为new的时候就是用char字节的方法申请的,delete的时候要对应。。
}
} template < class T >
inline
void* MemoryPool < T > :: alloc (size_t)
{
if (!next) {
expandTheFreeList();
} MemoryPool<T> *head = next;
next = head->next; return head;
} template < class T >
inline
void MemoryPool < T > :: free (void *doomed)
{
MemoryPool<T> *head = static_cast <MemoryPool<T> *> (doomed); head->next = next;
next = head;
} template < class T >
void MemoryPool < T > :: expandTheFreeList(int howMany)
{
// We must allocate an object large enough to contain the
// next pointer.
size_t size = (sizeof(T) > sizeof(MemoryPool<T> *)) ?
sizeof(T) : sizeof(MemoryPool<T> *); //MemoryPool<T> *runner = static_cast <MemoryPool<T> *>(new char [size]);
MemoryPool<T> *runner = (MemoryPool<T> *)(new char [size]); next = runner;
for (int i = ; i < howMany ; i++) {
//runner->next = static_cast <MemoryPool<T> *> new char [size];
runner->next = (MemoryPool<T> *)( new char [size]);
runner = runner->next;
}
runner->next = NULL;
} class Rational {
public:
Rational (int a = , int b = ) : n(a), d(b) {} void *operator new(size_t size) { return memPool->alloc(size); }
void operator delete(void *doomed,size_t size)
{ memPool->free(doomed); } static void newMemPool() { memPool = new MemoryPool <Rational>; }
static void deleteMemPool() { delete memPool; }
private:
int n; // Numerator
int d; // Denominator static MemoryPool <Rational> *memPool;
}; MemoryPool <Rational> *Rational::memPool = ; int main()
{
Rational *array[]; Rational::newMemPool(); // Start timing here for (int j = ; j < ; j++) {
for (int i = ; i < ; i++) {
array[i] = new Rational(i);
}
for (int i = ; i < ; i++) {
delete array[i];
}
} // Stop timing here Rational::deleteMemPool(); }
efficient c++,单线程内存池的更多相关文章
- 内存池-转载自IBM
[转载自IBM]讲的很好~推荐看看 6.1 自定义内存池性能优化的原理 如前所述,读者已经了解到"堆"和"栈"的区别.而在编程实践中,不可避免地要大量用到堆上的 ...
- C++实现简单的内存池
多进程编程多用在并发服务器的编写上,当收到一个请求时,服务器新建一个进程处理请求,同时继续监听.为了提高响应速度,服务器采用进程池的方法,在初始化阶段创建一个进程池,池中有许多预创建的进程,当请求到达 ...
- golang 内存池
一般来说,内存池都是采用预分配的方式,分为固定大小的和非固定大小块,固定大小的内存效率高,非固定大小灵活.同时,分为单线程和多线程版的,单线程不需要考虑并发问题. 一般内存池的实现思想:分配一块比较大 ...
- 内存分配(new/delete,malloc/free,allocator,内存池)
以下来源http://www.cnblogs.com/JCSU/articles/1051826.html 程序员们经常编写内存管理程序,往往提心吊胆.如果不想触雷,唯一的解决办法就是发现所有潜伏的地 ...
- 基于C/S架构的3D对战网络游戏C++框架_05搭建系统开发环境与Boost智能指针、内存池初步了解
本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...
- berkeley db 内存池分配机制
__memp_alloc() 注: MPOOL_ALLOC_SEARCH_DYN 没有 出现在 bdb document上, 也没出现在 除了mp_alloc外的代码里. 先删了 以便代码清楚. 按 ...
- NGINX 内存池有感
写在前面 写NGINX系列的随笔,一来总结学到的东西,二来记录下疑惑的地方,在接下来的学习过程中去解决疑惑. 也希望同样对NGINX感兴趣的朋友能够解答我的疑惑,或者共同探讨研究. 整个NGINX系列 ...
- 【uTenux实验】内存池管理(固定内存池和可变内存池)
1.固定内存池管理实验 内存管理是操作系统的一个基础功能.uTenux的内存池管理函数提供了基于软件的内存池管理和内存块分配管理.uTenux的内存池有固定大小的内存池和大小可变的内存池之分,它们被看 ...
- boost的线程池和内存池 智能指针
内存池为boost自带的 #include <boost/pool/pool.hpp> 或者另外一个开源的库: nedmalloc 一个高效率的库 线程池需要下载另外一个开源库 http: ...
随机推荐
- C#中委托和事件的区别实例解析
这篇文章主要介绍了C#中委托和事件的区别,并分别以实例形式展示了通过委托执行方法与通过事件执行方法,以及相关的执行流程与原理分析,需要的朋友可以参考下 本文实例分析了C#中委托和事件的区别,分享给大家 ...
- (转) 读取xml文件转成List<T>对象的两种方法
读取xml文件,是项目中经常要用到的,所以就总结一下,最近项目中用到的读取xml文件并且转成List<T>对象的方法,加上自己知道的另一种实现方法. 就以一个简单的xml做例子. xml格 ...
- 深入探析koa之中间件流程控制篇
koa被认为是第二代web后端开发框架,相比于前代express而言,其最大的特色无疑就是解决了回调金字塔的问题,让异步的写法更加的简洁.在使用koa的过程中,其实一直比较好奇koa内部的实现机理.最 ...
- 09_Java8操作集合的一些新特性
[使用forEach()结合Lambda表达式遍历集合] public class ForEachDemo { public static void main(String[] args) { Col ...
- union 中可以存储的是不带构造函数的类对象
union 中可以存储的是不带构造函数的类对象 否则不符合逻辑 为什么不符合逻辑?
- 3月3日(3) Binary Tree Preorder Traversal
原题 Binary Tree Preorder Traversal 没什么好说的... 二叉树的前序遍历,当然如果我一样忘记了什么是前序遍历的.. 啊啊.. 总之,前序.中序.后序,是按照根的位置来 ...
- bzoj 1005 HNOI2008 明明的烦恼
这题做的我欲哭无泪啊…… 我已经没心情多说啥了…… 高精度T啊!我太弱啊!改了一天啊!还不如滚粗啊! 想好式子在写啊! 能用高精度乘单精度就不要用高精度乘高精度啊! 能用高精度除单精度就不要用 ...
- Poj OpenJudge 百练 2632 Crashing Robots
1.Link: http://poj.org/problem?id=2632 http://bailian.openjudge.cn/practice/2632/ 2.Content: Crashin ...
- C++ VARIANT 学习小记录
一:为什么会有这个? 目前,计算机语言有很多(大哥,为什么不能就那么一样呢?),如C++.Java,此外还有JavaScript.VBScript等脚本语言,它们自立门派,各自维护自己的数据类型. C ...
- java学习笔记_GUI(1)
import javax.swing.*; public class Gui { public static void main(String[] args) { JFrame frame = new ...