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#编写windows服务程序
Windows Service这一块并不复杂,但是注意事项太多了,网上资料也很凌乱,偶尔自己写也会丢三落四的.所以本文也就产生了,本文不会写复杂的东西,完全以基础应用的需求来写,所以不会对Window ...
- usp_Copy_Unzip_DirFiles -- 拷贝,解压,列出文件名 from FTP Folder to Work Folder
CREATE PROC usp_Copy_Unzip_DirFiles @FTPPath NVARCHAR(4000)= '', -- ftp 文件夹路径 @WorkPath NVARCHAR(400 ...
- Commons-logging + Log4j
一.Commons-logging能帮我们做什么? 1.提供一个统一的日志接口,简单了操作,同时避免项目与某个日志实现系统紧密耦合 2.自动选择适当的日志实现系统 a.classpath下查找comm ...
- 229. Majority Element II My Submissions Question
Total Accepted: 23103 Total Submissions: 91679 Difficulty: Medium Given an integer array of size n, ...
- 版本控制工具--GIT 基本命令(1)
一.安装GIT,在官网上下载安装即可(下面模拟环境是window7) 二.基本操作: 1.创建GIT库: ①先使用mkdir命令创建一个空目录,再使用git init将该目录变成GIT库,会在该目录下 ...
- java访问webservice服务(一)
欢迎转载 http://www.cnblogs.com/shizhongtao/p/3433653.html 使用wsdl2java工具命令 一. 调出命令提示符cd到cxf的解压路径“D:\学 ...
- memset与NULL区别
memset与NULL区别 NULL与0 的区别 为什么强调一个malloc对应一个free 在一个结构体malloc,然后free,但是她的成员变量的malloc并没有free,还需要特别的free ...
- java学习笔记_GUI(4)
import javax.swing.*; import java.awt.event.*; import java.awt.*; class MyPanel_0 extends JPanel { p ...
- C#使用Zxing2.0生成二维码 带简单中心LOGO
参考:http://www.open-open.com/lib/view/open1379214678162.html 代码:http://files.cnblogs.com/halo/%E4%BA% ...
- [Oracle]Oracle学习小结(1)
1.查看Oracle数据库中的所有用户: (1)使用具有DBA权限的账户登录数据库: (2)执行select username from dba_users. SQL> conn sys 输入口 ...