/*********************************************************
在一些不确定内存总占用量的情形下,频繁的使用new申请内存,再通过链表
进行索引似乎是很常规的做法。自然,也很难做到随机定位。
下面的内存池类是用二层索引表来对内存进行大块划分,任何一个块均只需索
引3次即可定位。
索引数量,每索引块的分配单元数量,以及分配单元的字节长度均需为2的整数
次幂(为了运算时的效率)
//by:www.frombyte.com zhangyu(zhangyu.blog.51cto.com)
*********************************************************/
class MemTable
{
public:
MemTable(void);
public:
~MemTable(void);
public:
void CREATE(MemTableIn *in_m);
void DEL();
LPSTR NEW();//分配一个unit
LPSTR NEW_CONTINUEOUS(UINT n);//用于连续分配若干个unit
UINT NEW(UINT n); //用于可碎片方式分配若干个unit
LPSTR GET(UINT n);//用来获得第n个分配的指针地址
int get_totle_unitnum();
public:
MemTableIn in;
LPSTR **pDouble_Indirect;
LPSTR lpBitmap;
LPSTR *pIndirect; LPSTR m_lpFirstFree;
int nFree[];//0表示二级索引的自由,1表示1级索引的自由,2表示块自由索引号
INT32 m_EndBlkUseredUnits;
int m_Vblkbytes;
UINT m_UnitTotalNum;
UINT m_log2Rindexs,m_log2Runits,m_log2Rbitmap,m_log2Lindexs,m_log2Lunits,m_log2Lbitmap;
UINT m_log2UnitBytes;
UINT m_index2ID,m_index1ID,m_UnitID;
};
在一些不确定内存总占用量的情形下,频繁的使用new申请内存,再通过链表
进行索引似乎是很常规的做法。自然,也很难做到随机定位。
下面的内存池类是用二层索引表来对内存进行大块划分,任何一个块均只需索
引3次即可定位。
索引数量,每索引块的分配单元数量,以及分配单元的字节长度均需为2的整数
次幂(为了运算时的效率)

CPP内容如下:

 /**
* ffs - Find the first set bit in an int
* @x:
*
* Description...用来统计一个整型数据的最高为1的位,后面有多少位。
*换个说法:从最高位开始找1,找到1后,看这个二进制数据1000....000是2的几次方
*
* Returns:
*/
int ffs(int x)
{
int r = ; if (!x)
return ;
if (!(x & 0xffff)) {
x >>= ;
r += ;
}
if (!(x & 0xff)) {
x >>= ;
r += ;
}
if (!(x & 0xf)) {
x >>= ;
r += ;
}
if (!(x & )) {
x >>= ;
r += ;
}
if (!(x & )) {
x >>= ;
r += ;
}
return r;
}
LPSTR MemTree::GET(MemTreeHead *pHead,UINT n)
{
int t;
LPSTR lpt;
int i,ii;
//判断是否直接存储
if(n<m.rootDirectUnitNum)
return pHead->lpRootUnit + n*m.Vsizeof;
else
t=n-m.rootDirectUnitNum; for(i=;i<DEEP;i++)
{
if(t<TBT[i][])
break;
t-=TBT[i][];
}
//i便是深度,t是深度内的n
lpt=pHead->pROOT_INDEX[i-];
int D;
for(ii=;ii<i;ii++)
{
D=t /TBT[i][ii];
t=t % TBT[i][ii];
lpt=*(LPSTR*)(lpt+sizeof(LPSTR)*D);
}
return (lpt + t*m.Vsizeof); } MemTable::MemTable(void)
{
} MemTable::~MemTable(void)
{
//释放所有空间
for(int i=;i<in.nIndexNum;i++)
{
LPSTR *pp=pDouble_Indirect[i];
if(pp==NULL)
break;
for(int ii=;ii<in.nIndexNum;ii++)
{
LPSTR p=pp[ii];
if(p==NULL)
break;
else
delete [] p;
}
delete [] pp;
}
delete [] pDouble_Indirect;
}
void MemTable::CREATE(MemTableIn *in_m)
{
//1、初始化一些参考块
memset(&in,,sizeof(in));
in=*in_m;
m_UnitTotalNum=;
nFree[]=nFree[]=nFree[]=; m_Vblkbytes= in.nUnitBytes *in.nUnitPerIndex;
m_log2Runits=ffs(in.nUnitPerIndex)-;
m_log2Rindexs=ffs(in.nIndexNum)-;
m_log2UnitBytes=ffs(in.nUnitBytes)-; m_log2Lindexs=sizeof(UINT)*-m_log2Rindexs;
m_log2Lunits=sizeof(UINT)*-m_log2Runits; //2、初始化二级索引表
pDouble_Indirect=new LPSTR* [in.nIndexNum];
memset(pDouble_Indirect,,in.nIndexNum*sizeof(LPSTR));
nFree[]=in.nIndexNum;
}
LPSTR MemTable::NEW()
{
LPSTR lpReturn;
if(nFree[]==)//直接块用光了
{
if(nFree[]==)
{
if(nFree[]==)
return NULL;//写日志:达到最大分配数量 pIndirect=pDouble_Indirect[in.nIndexNum - nFree[]]=new LPSTR [in.nIndexNum];
memset(pIndirect,,in.nIndexNum*sizeof(LPSTR));
nFree[]=in.nIndexNum-; lpReturn=pIndirect[]=new char[m_Vblkbytes];
memset(lpReturn,,m_Vblkbytes);
nFree[]=in.nUnitPerIndex-;
m_lpFirstFree = lpReturn + in.nUnitBytes;
nFree[]--; }
else
{
lpReturn=pIndirect[in.nIndexNum - nFree[]]=new char[m_Vblkbytes];
memset(lpReturn,,m_Vblkbytes);
nFree[]--;
nFree[]=in.nUnitPerIndex-;
m_lpFirstFree = lpReturn + in.nUnitBytes;
}
}
else
{
lpReturn=m_lpFirstFree;
nFree[]--;
m_lpFirstFree += in.nUnitBytes;
}
m_UnitTotalNum++;
return lpReturn; }//by:www.frombyte.com zhangyu(zhangyu.blog.51cto.com)
UINT MemTable::NEW(UINT n)
{
UINT nReturn=m_UnitTotalNum;
for(int i=;i<n;i++)
NEW();
return nReturn; }
LPSTR MemTable::NEW_CONTINUEOUS(UINT n)
{
LPSTR lpReturn;
if(n>in.nUnitPerIndex)
return NULL; if(nFree[]>=n)
{
nFree[]-=n;
lpReturn=m_lpFirstFree;
m_UnitTotalNum+=n;
m_lpFirstFree += (n*in.nUnitBytes);
}
else
{
m_UnitTotalNum+=nFree[];//剩余空间保留、忽略
nFree[]=;
lpReturn=NEW();
nFree[] -= (n-);
m_lpFirstFree += ((n-)*in.nUnitBytes);
m_UnitTotalNum += (n-);
}
return lpReturn;
}
LPSTR MemTable::GET(UINT n)
{ //by:www.frombyte.com zhangyu(zhangyu.blog.51cto.com)
if(n>=m_UnitTotalNum)
return NULL;//写日志:超过范围
m_UnitID=n<< m_log2Lunits >>m_log2Lunits;
m_index1ID=n >> m_log2Runits;
m_index2ID=m_index1ID >> m_log2Rindexs;
m_index1ID=m_index1ID <<m_log2Lindexs >>m_log2Lindexs; return (pDouble_Indirect[m_index2ID][m_index1ID] + (m_UnitID<<m_log2UnitBytes)); }
void MemTable::DEL()
{ }

c++内存优化:二级间接索引模式内存池的更多相关文章

  1. SQL Server 内存优化表的索引设计

    测试的版本:SQL Server 2017 内存优化表上可以创建哈希索引(Hash Index)和内存优化非聚集(NONCLUSTERED)索引,这两种类型的索引也是内存优化的,称作内存优化索引,和基 ...

  2. linux内存优化之手工释放linux内存

    先介绍下free命令 Linux free命令用于显示内存状态. free指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等. 语法: free [- ...

  3. 试试SQLSERVER2014的内存优化表

    试试SQLSERVER2014的内存优化表 SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度. 现在,存储引擎已整合进当前的数据库管理系统,而使用先进内存技 ...

  4. SQLServer2014内存优化表评测

    SQLServer2014内存优化表评测 分类: SQL内存表2014-06-20 11:49 1619人阅读 评论(11) 收藏 举报 目录(?)[-] SQLServer2014的使用基本要求 内 ...

  5. SQLSERVER2014的内存优化表

    SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度. 现在,存储引擎已整合进当前的数据库管理系统,而使用先进内存技术来支持大规模OLTP工作负载. 就算如此, ...

  6. 试试SQLServer 2014的内存优化表

    SQL Server2014存储引擎:行存储引擎,列存储引擎,内存引擎 SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度. 现在,存储引擎已整合进当前的数据 ...

  7. 试试SQLServer 2014的内存优化表(转载)

    SQL Server2014存储引擎:行存储引擎,列存储引擎,内存引擎 SQL Server 2014中的内存引擎(代号为Hekaton)将OLTP提升到了新的高度. 现在,存储引擎已整合进当前的数据 ...

  8. Android 性能优化 - 详解内存优化的来龙去脉

    前言 APP内存的使用,是评价一款应用性能高低的一个重要指标.虽然现在智能手机的内存越来越大,但是一个好的应用应该将效率发挥到极致,精益求精. 这一篇中我们将着重介绍Android的内存优化.本文的篇 ...

  9. android 开发如何做内存优化

    不少人认为JAVA程序,因为有垃圾回收机制,应该没有内存泄露.其实如果我 们一个程序中,已经不再使用某个对象,但是因为仍然有引用指向它,垃圾回收器就无法回收它,当然该对象占用的内存就无法被使用,这就造 ...

随机推荐

  1. [Netty] - Netty IN ACTION(导言)

    最近没什么事儿做,刚好看到有需要网络编程的知识,java中有NIO和IO两种不同的方式,但是NIO的编写比较麻烦,刚好找到一个成熟的网络框架Netty.接下来的一个月就准备将Netty IN ACTI ...

  2. css中书写小三角

    我们在开发过程中,有很多的方向标签不是图片,而是用css方法书写上去的. 首先我们要了解原理,border的边框的脚步是45度角. 向左方向: width:0px: height:0px: borde ...

  3. 使用jQuery操作DOM

    一.DOM操作分为3类 1.DOM Core DOM Core不是Javascript的专属品,任何一种支持DOM的编程语言都可以使用它.它的用途不仅限于处理一种使用标记语言编写出来的文档 2.HTM ...

  4. Linux学习之Linux目录及文件系统

    以往的 Windows 一直是以存储介质为主的,主要以盘符(C 盘,D 盘...)及分区来实现文件管理,然后之下才是目录,目录就显得不是那么重要,除系统文件之外的用户文件放在任何地方任何目录也是没有多 ...

  5. ABP Zero 多租户管理

    ABPZero - 多租户管理 启用多租户 ASP.NET Boilerplate和module-zero可以运行多租户或单租户模式.多租户默认为禁用.我们可以在我们的模块PreInitialize方 ...

  6. 让SQL再快一点儿

    文章转载自「开发者圆桌」一个关于开发者入门.进阶.踩坑的微信公众号 SQL即结构化查询语言(Structured Query Language),是一种特殊目的的编程语言,是一种数据库查询和程序设计语 ...

  7. oracle expdp和impdp常用命令选项

    一.expdp导出数据库 1.按用户导出 expdp scott/tiger@orcl DIRECTORY=oracle_dmp dumpfile=bak.dmp schemas=scott vers ...

  8. laravel初次学习总结及一些细节

    最近学习了laravel,先简单谈谈学习的感受吧 刚开始一周多一点的时间先把laravel的开发文档看了一遍,,感觉刚开始接触时的感觉laravel的目录与thinkphp又不一样,它们的渲染模板的方 ...

  9. Objective-C日记-之KVC

    KVC(Key-Value-Coding?) 1, 概述 以字符串形式向对象的实例变量或属性(Property)发送或者获得值的方法. 2,用法 a,取值 @property (readwrite,c ...

  10. C++ 构造函数或析构函数调用虚函数

    构造函数和析构函数中的虚函数 在执行基类构造函数时,对象的派生类部分是未初始化的.实际上,此时对象还不是一个派生类对象. 为 了适应这种不完整,编译器将对象的类型视为在构造或析构期间发生了变化.在基类 ...