自己做的一个固定大小对象内存池,效率大概为原始的new/delete的2倍
提升不高,不过好处是可以多次申请小对象,一次释放。(只适应于无动态申请资源的class)
vs2012测试情况如下:


// CHchFixLenMemPool.h
#pragma once
#ifndef __CHchFixLenMemPool_H__
#define __CHchFixLenMemPool_H__
#include <exception>
#include <new> typedef struct __HchFixLenMemPoolLinkNode
{
__HchFixLenMemPoolLinkNode *m_next;
}SHchFixLenMemPoolLinkNode; class CHchFixLenMemPool
{
public:
CHchFixLenMemPool(size_t nFixLen, size_t nExpectObjectCnt = )
{
if ( nFixLen < (sizeof(void *) > sizeof(size_t) ? sizeof(void *) : sizeof(size_t)) )
{
throw std::exception("nFixLen < max(sizeof(void *), sizeof(size_t))");
} //必须对齐,不然有可能出现内存访问异常
m_nFixLen = (nFixLen + sizeof(int) - ) & ~(sizeof(int) - );
m_nExpectObjectCnt = nExpectObjectCnt; if (m_nExpectObjectCnt < )
{
m_nExpectObjectCnt = ;
} m_allocSpaceLink = m_freeSpaceLink = NULL;
allocFromSystem();
} ~CHchFixLenMemPool()
{
//遍历链表节点
while (m_allocSpaceLink)
{
SHchFixLenMemPoolLinkNode *pNext = m_allocSpaceLink->m_next;
delete [](void *)m_allocSpaceLink;
m_allocSpaceLink = pNext;
}
} void *alloc()
{
//如果存在已回收的空间,则直接分配出去
if (m_freeSpaceLink != NULL)
{
void *p = m_freeSpaceLink;
m_freeSpaceLink = m_freeSpaceLink->m_next;
return p;
} //不然需要从m_allocSpaceLink里面切一块出来
char *pRetSpace = m_currAllocSpace; //pRetSpace指向待返回的空间 //如果上次new出来的内存还没分配完,则直接分配即可
if (m_nLeft != )
{
--m_nLeft;
m_currAllocSpace += m_nFixLen;
return pRetSpace;
} //当前new出来的空间空间全部分配完 则需要重新向系统申请内存
allocFromSystem(); //这段跟前面分配逻辑是一样的
//考虑到cpu流水线预测,刻意这样重复写代码
pRetSpace = m_currAllocSpace;
--m_nLeft;
m_currAllocSpace += m_nFixLen;
return pRetSpace;
} void free(void *pSpace)
{
if (pSpace == NULL)
{
return;
} //如果回收空间链表为空,则直接修改m_allocSpaceLinke即可
SHchFixLenMemPoolLinkNode *p = (SHchFixLenMemPoolLinkNode *)pSpace;
if (m_allocSpaceLink == NULL)
{
m_allocSpaceLink = p;
m_allocSpaceLink->m_next = NULL;
return;
} //否则将当前空间插到链表头
p->m_next = m_freeSpaceLink;
m_freeSpaceLink = p;
return;
} private:
//从系统分配内存
void allocFromSystem()
{
SHchFixLenMemPoolLinkNode *pNextLink = m_allocSpaceLink;
//new失败会抛异常,不需要考虑
m_allocSpaceLink = (SHchFixLenMemPoolLinkNode *)
new char[sizeof(SHchFixLenMemPoolLinkNode) + m_nFixLen * m_nExpectObjectCnt]; m_allocSpaceLink->m_next = pNextLink;
m_nLeft = m_nExpectObjectCnt;
m_currAllocSpace = ((char *)m_allocSpaceLink) + sizeof(SHchFixLenMemPoolLinkNode);
} size_t m_nFixLen; //内存池定长
size_t m_nLeft; //已申请未分配个数
size_t m_nExpectObjectCnt; //每次申请多少个定长的空间 //当前可分配的空间指针
char *m_currAllocSpace; //回收空间链表 m_next指向下一个已回收空间
SHchFixLenMemPoolLinkNode *m_freeSpaceLink; //已向系统申请的空间链表
//链表中每个节点均指向new返回的指针
//m_next指向下一个已向申请空间
SHchFixLenMemPoolLinkNode *m_allocSpaceLink;
}; template<typename T>
T *newClassFromPool(CHchFixLenMemPool& objPool, const T& other)
{
T *pState = (T *)objPool.alloc();
new(pState) T(other);
return pState;
} template<typename T, typename T1>
T *newClassFromPool(CHchFixLenMemPool& objPool, const T1& param)
{
T *pState = (T *)objPool.alloc();
new(pState) T(param);
return pState;
} template<typename T>
T *newClassFromPool(CHchFixLenMemPool& objPool)
{
T *pState = (T *)objPool.alloc();
new(pState) T();
return pState;
} template<class T>
void deleteClassFromPool(CHchFixLenMemPool& objPool, T * pState)
{
pState->~T();
objPool.free(pState);
} #ifdef __POP_NEW_FLAG__
#pragma pop_macro("new")
#endif #endif
// testObjPool.cpp : Defines the entry point for the console application.
// #include "stdafx.h"
#include "CHchFixLenMemPool.h"
#ifdef WIN32
#include <Windows.h>
#endif
#include <stdio.h> class CSimpleBuffer
{
public:
CSimpleBuffer(size_t size = )
{
m_memSize = size;
m_pMem = new char[m_memSize];
} CSimpleBuffer(const CSimpleBuffer& other)
{
m_memSize = other.m_memSize;
m_pMem = new char[m_memSize];
memcpy(m_pMem, other.m_pMem, m_memSize);
} char *getMem()
{
return m_pMem;
} size_t getMemSize()
{
return m_memSize;
} ~CSimpleBuffer()
{
delete []m_pMem;
}
private:
size_t m_memSize;
char *m_pMem;
}; #ifdef WIN32 class CMyTiming
{
public:
CMyTiming()
{
m_startFlag = false;
} bool startTiming() //开始计时
{
if (m_startFlag)
{
return false;
}
m_startFlag = true; QueryPerformanceFrequency(&m_litmp); /*获得时钟频率*/
m_dff = m_litmp.QuadPart; QueryPerformanceCounter(&m_litmp); /*获得初始值*/
m_qtBeg = m_litmp.QuadPart; return true;
} double getTiming() //获得当前消耗时间
{
if (!m_startFlag)
{
return -;
} QueryPerformanceCounter(&m_litmp); /*获得终止值*/
m_qtEnd = m_litmp.QuadPart;
m_dfm = (m_qtEnd - m_qtBeg);
m_dft = ((double) m_dfm) / m_dff; /*获得对应的时间值*/
return m_dft;
} void endTiming() //停止计时
{
m_startFlag = false;
}
private:
bool m_startFlag;
LARGE_INTEGER m_litmp;
LONGLONG m_qtBeg, m_qtEnd, m_dff, m_dfm;
double m_dft;
};
#endif int _tmain(int argc, _TCHAR* argv[])
{
const int nTimes = ;
const int n = ;
CSimpleBuffer *pArray[nTimes];
CMyTiming runTimeInfo; printf("total new times %d\n", nTimes * n);
runTimeInfo.startTiming(); for (int i = ; i < n * nTimes; i++)
{
int nPos = i / n;
pArray[nPos] = new CSimpleBuffer();
pArray[nPos]->getMem()[] = '\0';
if (i % n != (n - )) delete pArray[nPos];
} for (int i = ; i < nTimes; i++)
{
int nPos = i / n;
strcpy(pArray[nPos]->getMem(), "hell8ffff fffff");
pArray[nPos]->getMem()[i % ] = '';
pArray[nPos]->getMem()[i % ] = i;
if (i % n == (n - )) delete pArray[nPos];
} printf("sec1 %.4f\n", runTimeInfo.getTiming()); runTimeInfo.endTiming();
runTimeInfo.startTiming();
CHchFixLenMemPool objPool(sizeof(CSimpleBuffer), ); for (int i = ; i < n * nTimes; i++)
{
int nPos = i / n;
pArray[nPos] = newClassFromPool<CSimpleBuffer, size_t>(objPool, );
pArray[nPos]->getMem()[] = '\0';
if (i % n != (n - )) deleteClassFromPool(objPool, pArray[nPos]);
} for (int i = ; i < nTimes; i++)
{
int nPos = i / n;
strcpy(pArray[nPos]->getMem(), "hell8ffff fffff");
pArray[nPos]->getMem()[i % ] = '';
pArray[nPos]->getMem()[i % ] = i;
if (i % n == (n - )) deleteClassFromPool(objPool, pArray[nPos]);
} printf("sec2 %.4f\n", runTimeInfo.getTiming()); return ;
}
自己做的一个固定大小对象内存池,效率大概为原始的new/delete的2倍的更多相关文章
- ExecutorService常用方法和newFixedThreadPool创建固定大小的线程池
1.ExecutorService: 是一个接口,继承了Executor: public interface ExecutorService extends Executor { } 2.Execut ...
- 【uTenux实验】内存池管理(固定内存池和可变内存池)
1.固定内存池管理实验 内存管理是操作系统的一个基础功能.uTenux的内存池管理函数提供了基于软件的内存池管理和内存块分配管理.uTenux的内存池有固定大小的内存池和大小可变的内存池之分,它们被看 ...
- Java网络与多线程系列之1:实现一个简单的对象池
前言 为什么要从对象池开始呢,先从一个网络IO操作的demo说起 比如下面这段代码,显而易见已经在代码中使用了一个固定大小的线程池,所以现在的重点在实现Runnble接口的匿名对象上,这个对象每次创建 ...
- Nginx数据结构之内存池
基本结构 1. ngx_pool_t struct ngx_pool_s { ngx_pool_data_t d; size_t max; ngx_pool_t *current; ngx_chain ...
- 6、java5线程池之固定大小线程池newFixedThreadPool
JDK文档说明: 创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程.在任意点,在大多数 nThreads 线程会处于处理任务的活动状态.如果在所有线程处于活动状态时提交附加任务,则 ...
- Hyper-V创建固定大小虚拟机
1.新建硬盘 点击确定,就创建好了一个固定大小的vhd文件,下面我们开始创建虚拟机. 2.创建虚拟机 输入虚拟机名称 选择第一代虚拟机 我这里给虚拟机分配512MB内存 网络配置 在这之前我们已经创建 ...
- php大力力 [042节] 今天做了一个删除功能
php大力力 [042节] 今天做了一个删除功能 if(isset($_GET['action'])){ if($_GET['action']=="del"){ $sql = &q ...
- nginx 内存池分析
最近nginx的源码刚好研究到内存池,这儿就看下nginx内存池的相关的东西. 一,为什么要使用内存池 大多数的解释不外乎提升程序的处理性能及减小内存中的碎片,对于性能优化这点主要体现在: (1)系统 ...
- 内存池-转载自IBM
[转载自IBM]讲的很好~推荐看看 6.1 自定义内存池性能优化的原理 如前所述,读者已经了解到"堆"和"栈"的区别.而在编程实践中,不可避免地要大量用到堆上的 ...
随机推荐
- SpringBoot实战(一)之构建RestFul风格
RestFul风格是一种非常流行的架构风格,相关实战可以参考我的这篇博客:SSM框架之RestFul示例 论文可参考:https://www.ics.uci.edu/~fielding/pubs/di ...
- JNI由浅入深_9_JNI 异常处理
1 .本地代码中如何缓存和抛出异常 下面的代码中演示了如何声明一个会抛出异常的本地方法.CatchThrow这个类声明了一个会抛出IllegalArgumentException异常的名叫doit的本 ...
- LCG(linear congruential generator): 一种简单的随机数生成算法
目录 LCG算法 python 实现 LCG算法 LCG(linear congruential generator)线性同余算法,是一个古老的产生随机数的算法.由以下参数组成: 参数 m a c X ...
- sharepoint OOS打开文档使用新窗口
总体说来就是在<a>标签上嵌入_blank $("a[onclick*='return DispEx'][target!='_blank']") .attr(" ...
- JavaScript编写简单的增加与减少元素
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 离线服务器下docker的部署与应用
一分钟内形成docker的模糊概念 网上很多文章避免将docker与虚拟机混为一谈,但对于初学者来说,完全可以将docker当做一种虚拟机技术,只需要牢牢记住一点最重要的区别:docker依赖于物理机 ...
- 【腾讯敏捷转型No.8】你爱上手机QQ了么?
上一篇文章<QQ邮箱如何利用敏捷做到中国第一>,“QQ邮箱之母”马化腾带领QQ邮箱团队,从流量思维向产品思维转变,“QQ邮箱之父”张小龙也是在这个敏捷转型过程中,剔除固有的成见,激发对优秀 ...
- Maven 逆向工程
pom.xml <build> <plugins> <plugin> <groupId>org.mybatis.generator</groupI ...
- vim内替换文件内容
几个常用的方法如下: :%s/foo/bar/g 把全部foo替换为bar,全局替换 :s/foo/bar/g 当前行替换foo为bar :%s/foo/bar/gc 替换每个foo为bar,但需要确 ...
- debian系统,启动Wireshark,出现Couldn't run /usr/bin/dumpcap in child process:权限不够
这是由于当前用户没有权限运行/usr/bin/dumpcap造成的./usr/bin/dumpcap是Wireshark的包捕获引擎. 先用ls命令看一下dumpcap的权限情况:xy@debian- ...