這段時(shí)間一直在做內(nèi)存分析和優(yōu)化相關(guān)的工作。幾點(diǎn)感悟,在此記錄下,歡迎有經(jīng)驗(yàn)人士共同探討。
一。有關(guān)tcmalloc
tcmalloc是google出的好東西,不了解的話自行g(shù)oogle之。他的最顯著作用是提升速度,內(nèi)部的緩存機(jī)制做得相當(dāng)了得。副作用是,加大了內(nèi)存占用,而且會(huì)隱藏了代碼中潛在的bug。用和不用,無(wú)非是對(duì)空間和時(shí)間的權(quán)衡取舍。優(yōu)化內(nèi)存使用是必然的,但不要等價(jià)于節(jié)省了程序內(nèi)存占用。個(gè)人強(qiáng)烈建議:即便用它的話,也在項(xiàng)目后期加上。因?yàn)榍懊嬲f(shuō)過(guò),這貨會(huì)隱藏代碼中潛在的bug,而且緩存的存在極不利于內(nèi)存占用分析。最后說(shuō)一點(diǎn),一開(kāi)始使用它的時(shí)候,很不確定一點(diǎn):到底起作用沒(méi)有?到底起作用沒(méi)有?問(wèn)百度和google,也沒(méi)找到方便快捷的方法。其實(shí),這個(gè)問(wèn)題很好解決,把libtcmalloc_minimal.dll刪掉,如果程序啟動(dòng)不起來(lái),那自然就起作用了。
二。有關(guān)win7
win7相比xp多了個(gè)SuperFetch功能,這是相同程序在win7下比在Xp下占用內(nèi)存要多不少的主要原因(對(duì)我們的游戲來(lái)講,win7普遍比Xp多個(gè)兩三百M(fèi),用tcmalloc比不用tcmalloc也多個(gè)幾百M(fèi))。和前面所講的tcmalloc類似,占用內(nèi)存多不代表不好。最簡(jiǎn)單直觀的證明,我們游戲在win7下的啟動(dòng)速度明顯快于Xp下的啟動(dòng)速度,用tcmalloc的啟動(dòng)速度明顯快于不用tcmalloc的啟動(dòng)速度。所以說(shuō),win7這個(gè)緩存機(jī)制,從原理上來(lái)講,是很類似于tcmalloc的。對(duì)開(kāi)發(fā)人員來(lái)說(shuō),缺點(diǎn)也很明顯,不方便分析程序內(nèi)存占用情況。很多時(shí)候你會(huì)有這樣的感覺(jué):資源該釋放的都釋放了,但內(nèi)存降不下來(lái),明明不該占用這么多啊。。看到這,不要再糾結(jié)了,是緩沖機(jī)制在作怪。
三。有關(guān)小對(duì)象分配
緩存機(jī)制會(huì)增大內(nèi)存占用,這點(diǎn)在小對(duì)象很多,頻繁new,delete的時(shí)候特別明顯?梢韵胂螅10*1024次new 1個(gè)1Kb的對(duì)象,然后對(duì)應(yīng)delete” 和 “10次new 1個(gè)1M的對(duì)象,然后對(duì)應(yīng)delete”,對(duì)內(nèi)存的影響是相當(dāng)不同的。甚至對(duì)于第一種情況來(lái)說(shuō),“每次new出來(lái),然后馬上delete” 和 “全部new出來(lái),然后依次delete”都有很大的不同。內(nèi)存里面道道多著呢,絕不僅僅是表面上的new,delete,malloc,free這么簡(jiǎn)單,你要深入了解操作系統(tǒng)底層的知識(shí)才可能理解簡(jiǎn)單的表象背后究竟隱藏了怎樣的故事。盡量不要再重復(fù)“生成,使用,銷毀”這個(gè)過(guò)程了,建立小對(duì)象緩沖池吧。比如,游戲里面的傷血數(shù)字,小地圖上的坐標(biāo)圖標(biāo)等等。
四。有關(guān)工具的使用
很多人會(huì)推薦建一個(gè)基類,重載new,delete操作符,然后程序里面所有需要new和delete的對(duì)象都從那個(gè)基類繼承下來(lái),以此來(lái)跟蹤內(nèi)存使用狀況。這個(gè)可以有,但操作難度有點(diǎn)大,程序維護(hù)成本也高。你不能保證組里的所有人在新建一個(gè)類(甚至struct)的時(shí)候都有那個(gè)意識(shí)去從那個(gè)基類上繼承下來(lái)。所以,最好的辦法是熟練掌握相關(guān)工具。這里強(qiáng)烈推薦windbg的!heap擴(kuò)展命令,以及配套的gflags,DH,UMDH工具。window底下還是自己的windbg最牛叉。Intel的那套工具也很強(qiáng)大,但速度慢,占用內(nèi)存多,拿它跑我們程序的話,半小時(shí)左右才進(jìn)到大廳,沒(méi)能進(jìn)入到PVE場(chǎng)景就因?yàn)閮?nèi)存占用過(guò)大而退出了。
關(guān)于緩存機(jī)制的存在會(huì)隱藏代碼潛在bug的例子見(jiàn)下。感興趣的同學(xué)自己配置tcmalloc試驗(yàn)一下,相信會(huì)有一個(gè)很直觀的感受。
1 #include<iostream> 2 #include<map> 3 #include<string.h> 4 using namespace std; 5 6 typedef std::map<int,std::string> MapIntString; 7 MapIntString mMaps; 8 9 int main() 10 { 11 mMaps.clear(); 12 13 for(int i = 0;i < 6;i++) 14 { 15 mMaps.insert(MapIntString::value_type(i,"a")); 16 } 17 MapIntString::iterator it; 18 for(it = mMaps.begin(); it != mMaps.end();it++) 19 { 20 if(it == mMaps.begin()) 21 { 22 mMaps.erase(it); 23 } 24 } 25 system("pause"); 26 return 0; 27 }