提升不高,不过好处是可以多次申请小对象,一次释放。(只适应于无动态申请资源的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 = 0){ 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) - 1) & ~(sizeof(int) - 1);m_nExpectObjectCnt = nExpectObjectCnt;if (m_nExpectObjectCnt < 1024){m_nExpectObjectCnt = 1024;}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 != 0){--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 = 32){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 WIN32class 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 -1;}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;
};
#endifint _tmain(int argc, _TCHAR* argv[])
{const int nTimes = 209600;const int n = 8000;CSimpleBuffer *pArray[nTimes];CMyTiming runTimeInfo;printf("total new times %d\n", nTimes * n);runTimeInfo.startTiming();for (int i = 0; i < n * nTimes; i++){int nPos =  i / n;pArray[nPos] = new CSimpleBuffer(64);pArray[nPos]->getMem()[0] = '\0';if (i % n != (n - 1)) delete pArray[nPos];}for (int i = 0; i < nTimes; i++){int nPos =  i / n;strcpy(pArray[nPos]->getMem(), "hell8ffff                                  fffff");pArray[nPos]->getMem()[i % 64] = '2';pArray[nPos]->getMem()[i % 32] =  i;if (i % n == (n - 1)) delete pArray[nPos];}printf("sec1 %.4f\n", runTimeInfo.getTiming());runTimeInfo.endTiming();runTimeInfo.startTiming();CHchFixLenMemPool objPool(sizeof(CSimpleBuffer), 8096);for (int i = 0; i < n * nTimes; i++){int nPos =  i / n;pArray[nPos] = newClassFromPool<CSimpleBuffer, size_t>(objPool, 64);pArray[nPos]->getMem()[0] = '\0';if (i % n != (n - 1)) deleteClassFromPool(objPool, pArray[nPos]);}for (int i = 0; i < nTimes; i++){int nPos =  i / n;strcpy(pArray[nPos]->getMem(), "hell8ffff                                  fffff");pArray[nPos]->getMem()[i % 64] = '2';pArray[nPos]->getMem()[i % 32] =  i;if (i % n == (n - 1)) deleteClassFromPool(objPool, pArray[nPos]);}printf("sec2 %.4f\n", runTimeInfo.getTiming());return 0;
}

View Code

转载于:https://www.cnblogs.com/kingstarer/p/6986636.html

自己做的一个固定大小对象内存池,效率大概为原始的new/delete的2倍相关推荐

  1. 简易的实现对象内存池

    简易的实现对象内存池 MemoryNode结构体是保存每一个申请的内存节点,然后构成一个单链表. MemoryNodeList 结构体是保存的是每一块内存,当上一个内存块用完时,再次创建一个内存块. ...

  2. 列表中的字符串成员 转化为 整型成员 。如:将[‘2‘, ‘1‘] 转化为:[2, 1]、map()返回的是一个可迭代对象内存地址、join(可迭代对象),要注意:可迭代对象中的成员必须是字符串类型

    注意: 1.map()返回的是一个可迭代对象的内存地址,如果要看它具体的值,有两种方式: 法1:在map()前面,加list( ).tuple( ).set( ),将它强制转化为列表.元组.集合类型. ...

  3. C++实现简单的固定大小内存分配器

    背景介绍 最近在了解性能优化相关的知识,了解到内存分配是一个可优化性能的方向,在相关书籍中看到一个固定大小的内存分配器实现,觉得挺有意思的,这里跟大家分享, 据说比通用的内存分配malloc()性能有 ...

  4. java timetasker_Java网络与多线程系列之1:实现一个简单的对象池

    前言 为什么要从对象池开始呢,先从一个网络IO操作的demo说起 比如下面这段代码,显而易见已经在代码中使用了一个固定大小的线程池,所以现在的重点在实现Runnble接口的匿名对象上,这个对象每次创建 ...

  5. 【项目】实现一个mini的tcmalloc(高并发内存池)

    文章目录 tcmalloc 池化技术 内存池解决的问题 malloc的相关知识 玩具malloc原理简述 ptmalloc简述 铺垫 chunk 线程安全 小结 实现一个定长内存池 原理 代码 测试 ...

  6. 我用飞桨做了一个可回收垃圾材料分类机

      随着社会生产力的发展,工业化.城镇化的兴起和人口增加,人类社会产生的垃圾与日俱增,加剧了全球范围内的资源短缺和环境污染,对自然环境和人体健康带来了巨大的挑战. 从中国新能源网和中国再生资源回收利用 ...

  7. 中石油训练赛 - Gone Fishing(固定大小的圆可以覆盖最多的点)

    题目大意:在二维平面中给出 n 个点,再给出一个固定大小的圆,问如何放置这个圆可以使其覆盖最多的点 题目分析:首先不难想到一种 n^3 的做法,就是两层循环去枚举两个点,因为两个不同的点就可以确定下来 ...

  8. php如何把图片铺满,PHP如何裁剪图片成固定大小

    做一个首页调用图像,有时需要获得固定大小的图像,因为首页的图像位置通常由设计人员指定好了,如果是做最新发布图像调用,因为不知道客户会上传什么比例的图像,所以,有时候也就没有办法确定图像的比例,前台页面 ...

  9. 一个轻量级内存池的实现与细节

    引言 内存池作为一种的内存管理机制被广泛地运用于各种领域当中,内存池拥有快速的内存分配与更加健壮的管理机制,同时在不同的平台与环境当中也拥有不同的实现方式,本文提出一种轻量级的内存池实现,可以非常方便 ...

最新文章

  1. 从终端运行React Native App时出错(iOS)
  2. 安装和配置SQL Server 2016 With SP1
  3. 战神引擎修改服务器时间,修改战神引擎手游进入游戏公告内容教程
  4. 使用python发送邮件和接收邮件
  5. 【Boost】boost库中thread多线程详解13——线程标识符
  6. vmware centos7 扩展容量
  7. js数组去重,合集等操作
  8. 流线动态图python_Node.js Stream(流)
  9. 【汇编语言】程序设计过程,如何避免数据类型匹配错误?
  10. 拳王公社:网络引流的“4大核心秘诀“,让客户源源不断地加你
  11. .NET下使用ufun函数取CAM操作的进给速度
  12. 如何改变Static Text控件中文字的字体,字体大小及颜色。
  13. 密实逃脱1深红色房间攻略
  14. 微型计算机的分类通常以什么来划分,微机的分类通常以微处理器的什么来划分...
  15. Java创建型设计模式之简单工厂,工厂方法,抽象工厂
  16. mysql数据恢复某一时间点_mysql时间点数据恢复
  17. python画十字_Python解决十字消除棋
  18. 如何在直播、会议、视频中使用虚拟形象
  19. vivos9e防抖功能设置教程
  20. Android 点击屏幕空白处隐藏软键盘

热门文章

  1. 浅谈android hook技术
  2. Android短信发送流程之普通短信发送(原)
  3. Changes in Android 7 Nougat
  4. SpringBoot使用@Transactional的类手动注入失败
  5. 卸料装置弹性零件的计算方法_冲裁模卸料板的设计
  6. 安卓抓包工具 linux,Android 下使用tcpdump网络抓包方法
  7. jar包打补丁 jar -uf_windows下批处理指定不同jdk版本运行jar包
  8. android 关闭软键盘_HTC官方社区明天正式关闭,收入持续下滑或是直接原因
  9. 模型学习 - HNN、RBM、DBN
  10. 如何在Windows7下删除Ubuntu开机引导项