c++内存优化:二级间接索引模式内存池
1 /********************************************************* 2 在一些不确定内存总占用量的情形下,频繁的使用new申请内存,再通过链表 3 进行索引似乎是很常规的做法。自然,也很难做到随机定位。 4 下面的内存池类是用二层索引表来对内存进行大块划分,任何一个块均只需索 5 引3次即可定位。 6 索引数量,每索引块的分配单元数量,以及分配单元的字节长度均需为2的整数 7 次幂(为了运算时的效率) 8 //by:www.frombyte.com zhangyu(zhangyu.blog.51cto.com) 9 *********************************************************/ 10 class MemTable 11 { 12 public: 13 MemTable(void); 14 public: 15 ~MemTable(void); 16 public: 17 void CREATE(MemTableIn *in_m); 18 void DEL(); 19 LPSTR NEW();//分配一个unit 20 LPSTR NEW_CONTINUEOUS(UINT n);//用于连续分配若干个unit 21 UINT NEW(UINT n); //用于可碎片方式分配若干个unit 22 LPSTR GET(UINT n);//用来获得第n个分配的指针地址 23 int get_totle_unitnum(); 24 public: 25 MemTableIn in; 26 LPSTR **pDouble_Indirect; 27 LPSTR lpBitmap; 28 LPSTR *pIndirect; 29 30 LPSTR m_lpFirstFree; 31 int nFree[3];//0表示二级索引的自由,1表示1级索引的自由,2表示块自由索引号 32 INT32 m_EndBlkUseredUnits; 33 int m_Vblkbytes; 34 UINT m_UnitTotalNum; 35 UINT m_log2Rindexs,m_log2Runits,m_log2Rbitmap,m_log2Lindexs,m_log2Lunits,m_log2Lbitmap; 36 UINT m_log2UnitBytes; 37 UINT m_index2ID,m_index1ID,m_UnitID; 38 };
在一些不确定内存总占用量的情形下,频繁的使用new申请内存,再通过链表 进行索引似乎是很常规的做法。自然,也很难做到随机定位。 下面的内存池类是用二层索引表来对内存进行大块划分,任何一个块均只需索
引3次即可定位。 索引数量,每索引块的分配单元数量,以及分配单元的字节长度均需为2的整数 次幂(为了运算时的效率)
CPP内容如下:
1 /** 2 * ffs - Find the first set bit in an int 3 * @x: 4 * 5 * Description...用来统计一个整型数据的最高为1的位,后面有多少位。 6 *换个说法:从最高位开始找1,找到1后,看这个二进制数据1000....000是2的几次方 7 * 8 * Returns: 9 */ 10 int ffs(int x) 11 { 12 int r = 1; 13 14 if (!x) 15 return 0; 16 if (!(x & 0xffff)) { 17 x >>= 16; 18 r += 16; 19 } 20 if (!(x & 0xff)) { 21 x >>= 8; 22 r += 8; 23 } 24 if (!(x & 0xf)) { 25 x >>= 4; 26 r += 4; 27 } 28 if (!(x & 3)) { 29 x >>= 2; 30 r += 2; 31 } 32 if (!(x & 1)) { 33 x >>= 1; 34 r += 1; 35 } 36 return r; 37 } 38 LPSTR MemTree::GET(MemTreeHead *pHead,UINT n) 39 { 40 int t; 41 LPSTR lpt; 42 int i,ii; 43 //判断是否直接存储 44 if(n<m.rootDirectUnitNum) 45 return pHead->lpRootUnit + n*m.Vsizeof; 46 else 47 t=n-m.rootDirectUnitNum; 48 49 for(i=1;i<DEEP;i++) 50 { 51 if(t<TBT[i][0]) 52 break; 53 t-=TBT[i][0]; 54 } 55 //i便是深度,t是深度内的n 56 lpt=pHead->pROOT_INDEX[i-1]; 57 int D; 58 for(ii=1;ii<i;ii++) 59 { 60 D=t /TBT[i][ii]; 61 t=t % TBT[i][ii]; 62 lpt=*(LPSTR*)(lpt+sizeof(LPSTR)*D); 63 } 64 return (lpt + t*m.Vsizeof); 65 66 } 67 68 MemTable::MemTable(void) 69 { 70 } 71 72 MemTable::~MemTable(void) 73 { 74 //释放所有空间 75 for(int i=0;i<in.nIndexNum;i++) 76 { 77 LPSTR *pp=pDouble_Indirect[i]; 78 if(pp==NULL) 79 break; 80 for(int ii=0;ii<in.nIndexNum;ii++) 81 { 82 LPSTR p=pp[ii]; 83 if(p==NULL) 84 break; 85 else 86 delete [] p; 87 } 88 delete [] pp; 89 } 90 delete [] pDouble_Indirect; 91 } 92 void MemTable::CREATE(MemTableIn *in_m) 93 { 94 //1、初始化一些参考块 95 memset(&in,0,sizeof(in)); 96 in=*in_m; 97 m_UnitTotalNum=0; 98 nFree[0]=nFree[1]=nFree[2]=0; 99 100 m_Vblkbytes= in.nUnitBytes *in.nUnitPerIndex; 101 m_log2Runits=ffs(in.nUnitPerIndex)-1; 102 m_log2Rindexs=ffs(in.nIndexNum)-1; 103 m_log2UnitBytes=ffs(in.nUnitBytes)-1; 104 105 m_log2Lindexs=sizeof(UINT)*8-m_log2Rindexs; 106 m_log2Lunits=sizeof(UINT)*8-m_log2Runits; 107 108 109 110 //2、初始化二级索引表 111 pDouble_Indirect=new LPSTR* [in.nIndexNum]; 112 memset(pDouble_Indirect,0,in.nIndexNum*sizeof(LPSTR)); 113 nFree[0]=in.nIndexNum; 114 } 115 LPSTR MemTable::NEW() 116 { 117 LPSTR lpReturn; 118 if(nFree[2]==0)//直接块用光了 119 { 120 if(nFree[1]==0) 121 { 122 if(nFree[0]==0) 123 return NULL;//写日志:达到最大分配数量 124 125 pIndirect=pDouble_Indirect[in.nIndexNum - nFree[0]]=new LPSTR [in.nIndexNum]; 126 memset(pIndirect,0,in.nIndexNum*sizeof(LPSTR)); 127 nFree[1]=in.nIndexNum-1; 128 129 lpReturn=pIndirect[0]=new char[m_Vblkbytes]; 130 memset(lpReturn,0,m_Vblkbytes); 131 nFree[2]=in.nUnitPerIndex-1; 132 m_lpFirstFree = lpReturn + in.nUnitBytes; 133 nFree[0]--; 134 135 } 136 else 137 { 138 lpReturn=pIndirect[in.nIndexNum - nFree[1]]=new char[m_Vblkbytes]; 139 memset(lpReturn,0,m_Vblkbytes); 140 nFree[1]--; 141 nFree[2]=in.nUnitPerIndex-1; 142 m_lpFirstFree = lpReturn + in.nUnitBytes; 143 } 144 } 145 else 146 { 147 lpReturn=m_lpFirstFree; 148 nFree[2]--; 149 m_lpFirstFree += in.nUnitBytes; 150 } 151 m_UnitTotalNum++; 152 return lpReturn; 153 154 }//by:www.frombyte.com zhangyu(zhangyu.blog.51cto.com) 155 UINT MemTable::NEW(UINT n) 156 { 157 UINT nReturn=m_UnitTotalNum; 158 for(int i=0;i<n;i++) 159 NEW(); 160 return nReturn; 161 162 } 163 LPSTR MemTable::NEW_CONTINUEOUS(UINT n) 164 { 165 LPSTR lpReturn; 166 if(n>in.nUnitPerIndex) 167 return NULL; 168 169 if(nFree[2]>=n) 170 { 171 nFree[2]-=n; 172 lpReturn=m_lpFirstFree; 173 m_UnitTotalNum+=n; 174 m_lpFirstFree += (n*in.nUnitBytes); 175 } 176 else 177 { 178 m_UnitTotalNum+=nFree[2];//剩余空间保留、忽略 179 nFree[2]=0; 180 lpReturn=NEW(); 181 nFree[2] -= (n-1); 182 m_lpFirstFree += ((n-1)*in.nUnitBytes); 183 m_UnitTotalNum += (n-1); 184 } 185 return lpReturn; 186 } 187 LPSTR MemTable::GET(UINT n) 188 { //by:www.frombyte.com zhangyu(zhangyu.blog.51cto.com) 189 if(n>=m_UnitTotalNum) 190 return NULL;//写日志:超过范围 191 m_UnitID=n<< m_log2Lunits >>m_log2Lunits; 192 m_index1ID=n >> m_log2Runits; 193 m_index2ID=m_index1ID >> m_log2Rindexs; 194 m_index1ID=m_index1ID <<m_log2Lindexs >>m_log2Lindexs; 195 196 return (pDouble_Indirect[m_index2ID][m_index1ID] + (m_UnitID<<m_log2UnitBytes)); 197 198 } 199 void MemTable::DEL() 200 { 201 202 203 }