游戲中的內存管理,也可以叫做內存池,好像有些也叫對象池,其實方法不少。我就講哈我自己做的點點經(jīng)驗和想法。
對應不同的類,使用模板類是肯定的。有些類可能不需要自動調用構造和析構,內存分配器就分出來了,就只負責分配對象的內存。方便起見,還是要有new和delete功能的對應方法,那就另外用一個模板類包裝內存分配器,是外部使用的類,New函數(shù)取得對象內存后再調用構造函數(shù),也要有malloc和free直接調用內存分配器的對應函數(shù)。
內存到底預分配多大?其實不好說,但是也是可預測的,實際測試統(tǒng)計之后還是會找到一個比較可靠的值。其實內存不必一次就分配那么多,雖然最大峰值是MAX,大部分時間使用量都是遠小于MAX的。內存按組分配要好些,MAX分成多個組,先分配一個組用到,不夠了用完的時候,再要一個組,這樣子使用率要高些。組在完全沒有使用的情況下是可以被回收的,是否要被回收可以變動。這也不會降低好多效率,組的數(shù)量不會很多,而且應該更加內存使用的情況而定,一個組里面包含多少個對象也是可調節(jié)的,測試后會有一個較好的值。
大概說哈結構嘛,內存分配器(allocator)有malloc和free,組(memorygroup)的單向鏈表,也可以用雙向鏈表我是為了節(jié)約些內存。通過模板參數(shù)把類型(T)、組數(shù)(groupsize)、對象數(shù)(objectsize)傳給組。
下面有簡易代碼說明:
外部使用的內存管理類包裝內存分配器,實現(xiàn)了malloc和free直接調用內存分配器的,還有new和delete函數(shù)是在取得地址后調用構造和調用析構后再傳遞指針。為了安全起見,用特例化把new和delete與malloc和free分離開,一個實例化的模板類只能調用其中一對函數(shù)。
為了使用的安全起見,用宏釋放對象指針同時把對象指針賦值為0,因為使用了內存管理器所以與一般的釋放宏不同需要傳入內存管理。
后面講哈內存使用的不同情況,組數(shù)量和對象數(shù)量設定的一點想法。
對應不同的類,使用模板類是肯定的。有些類可能不需要自動調用構造和析構,內存分配器就分出來了,就只負責分配對象的內存。方便起見,還是要有new和delete功能的對應方法,那就另外用一個模板類包裝內存分配器,是外部使用的類,New函數(shù)取得對象內存后再調用構造函數(shù),也要有malloc和free直接調用內存分配器的對應函數(shù)。
內存到底預分配多大?其實不好說,但是也是可預測的,實際測試統(tǒng)計之后還是會找到一個比較可靠的值。其實內存不必一次就分配那么多,雖然最大峰值是MAX,大部分時間使用量都是遠小于MAX的。內存按組分配要好些,MAX分成多個組,先分配一個組用到,不夠了用完的時候,再要一個組,這樣子使用率要高些。組在完全沒有使用的情況下是可以被回收的,是否要被回收可以變動。這也不會降低好多效率,組的數(shù)量不會很多,而且應該更加內存使用的情況而定,一個組里面包含多少個對象也是可調節(jié)的,測試后會有一個較好的值。
大概說哈結構嘛,內存分配器(allocator)有malloc和free,組(memorygroup)的單向鏈表,也可以用雙向鏈表我是為了節(jié)約些內存。通過模板參數(shù)把類型(T)、組數(shù)(groupsize)、對象數(shù)(objectsize)傳給組。
下面有簡易代碼說明:
1 template<typename T,int gs,int os>
2 class Allocator
3 {
4 T * malloc();
5 void free(void * p);
6
7 MemoryGroup * grouplist;
8 };
組是內存分配器的內部類,組才真正調用系統(tǒng)malloc分配整塊內存,按類數(shù)分給對象內存(memoryobject)數(shù)組分別保存地址。2 class Allocator
3 {
4 T * malloc();
5 void free(void * p);
6
7 MemoryGroup * grouplist;
8 };
1 struct MemoryObject
2 {
3 T * p;
4 MemoryObject * next;
5 };
6 struct MemoryGroup
7 {
8 MemoryObject * freelist;
9 MemoryObject objlist[cs];
10 MemoryGroup * next;
11 };
組維護一個空閑對象內存鏈表也是單向鏈表,當內存分配器需要地址的時候,組就把空閑鏈表中的一個對象內存返回,并把它從鏈表中刪除。當內存分配器要釋放對象的時候,對象指針傳遞給組,組進行效驗是否由該組分配,如果是就簡單的找到對應對象內存,添加到空閑鏈表。2 {
3 T * p;
4 MemoryObject * next;
5 };
6 struct MemoryGroup
7 {
8 MemoryObject * freelist;
9 MemoryObject objlist[cs];
10 MemoryGroup * next;
11 };
外部使用的內存管理類包裝內存分配器,實現(xiàn)了malloc和free直接調用內存分配器的,還有new和delete函數(shù)是在取得地址后調用構造和調用析構后再傳遞指針。為了安全起見,用特例化把new和delete與malloc和free分離開,一個實例化的模板類只能調用其中一對函數(shù)。
1 template<class T,int gs,int cs,bool nc,bool ar>
2 class MemoryManager
3 {
4 T * malloc();
5 void free(void * p);
6 };
7
8 template<class T,int gs,int cs,bool nc,bool ar>
9 class MemoryManager<T,gs,cs,true,ar>
10 {
11 T * new();
12 void delete(void * p);
13 };
模板參數(shù)的第4個參數(shù)(needconstruct)選擇使用哪一對函數(shù),第5個參數(shù)(autorecycle)決定要不要在組完全未使用時回收組。當然回收組是可以動態(tài)改變的一個選擇,所以第5個參數(shù)可以通過函數(shù)參數(shù)傳入。回收組可以在內存分配器是否對象時檢測組的使用情況,為了跟蹤使用情況可以在組內部附加一個計數(shù)器統(tǒng)計未使用對象數(shù)量,初始是設定的對象數(shù),使用時減1回收時加1,這個計數(shù)器在以后還可以計數(shù)使用率等,作為調試和測試信息輸出。2 class MemoryManager
3 {
4 T * malloc();
5 void free(void * p);
6 };
7
8 template<class T,int gs,int cs,bool nc,bool ar>
9 class MemoryManager<T,gs,cs,true,ar>
10 {
11 T * new();
12 void delete(void * p);
13 };
為了使用的安全起見,用宏釋放對象指針同時把對象指針賦值為0,因為使用了內存管理器所以與一般的釋放宏不同需要傳入內存管理。
1 #define FREE(m,p) { if (p) { m.free(p); p=0; } }
2 #define DELETE(m,p) { if (p) { m.delete(p); p=0; } }
基本上就是這么多啦,其實也不是黑復雜的東西。2 #define DELETE(m,p) { if (p) { m.delete(p); p=0; } }
后面講哈內存使用的不同情況,組數(shù)量和對象數(shù)量設定的一點想法。
new delete是很好用的。但是如果需要頻繁使用的時候,會造成內存粹片。當下一次再要分配的時候,如果系統(tǒng)發(fā)現(xiàn)找不到足夠大的空間來分配。就會進行內存整理。調整內存頁面數(shù)據(jù)。 這個整理數(shù)據(jù)的過程是很消耗時間的。(相對程序執(zhí)行時間來說)。 而通過預分配并重載new delete。可以在一定程序上避免重復new delete時產生的額外開銷。
這就是傳說中的內存振蕩和內存碎片。。。
上面的內存管理,是現(xiàn)在普遍采用的方法中的其中一種,并非新鮮事。 如果你覺得大家不用new delete是無聊。那你可以寫篇貼子來噴。 但是如果你是在自己沒有完全理解的情況下說這樣的話,那我會很有意見。 有些東西,不能靠自己猜,特別是C/C++。
我不知道你是不是想要這個答案。或許,你指的是別樣!!!
看了下你發(fā)的這個介紹,貌似很高深。 主要是針對多核結構,都采用多線程和安全檢測了。。我QQ是247869291,可以發(fā)到我QQ郵箱,謝謝哦!
好好琢磨