如何让手游内存占用更小?从内存消耗iOS实时统计开始
一,問(wèn)題
在之前的手游項(xiàng)目中,內(nèi)存使用過(guò)多,都開(kāi)始崩潰了,所以得做iOS內(nèi)存統(tǒng)計(jì)。內(nèi)存統(tǒng)計(jì)有好幾種方法:XCode內(nèi)存使用統(tǒng)計(jì)、UnityInternalProfile內(nèi)存統(tǒng)計(jì),Mono內(nèi)存統(tǒng)計(jì)等方法。
二、測(cè)試研究
但是XCode統(tǒng)計(jì)需要連手機(jī),UnityInternalProfile的內(nèi)存統(tǒng)計(jì)值與XCode內(nèi)存統(tǒng)計(jì)值差距又太大,崩潰時(shí)的內(nèi)存值跟誰(shuí)有關(guān)系?如何在手機(jī)上自己顯示內(nèi)存總量?后面就自己琢磨怎樣實(shí)現(xiàn)一個(gè)適合的內(nèi)存統(tǒng)計(jì)功能。
研究了下UnityInternalProfile,發(fā)現(xiàn)它拿的是mach_base_task_info里的resident_size(物理內(nèi)存占用)。
?
然后我做了個(gè)測(cè)試,每幾幀分配使用一定大小的內(nèi)存,然后打印出xcode統(tǒng)計(jì)的內(nèi)存和resident_size。
?
橫坐標(biāo)是時(shí)間,縱坐標(biāo)是內(nèi)存。
resident_size值的增長(zhǎng)隨著內(nèi)存增長(zhǎng),但增長(zhǎng)到一定程度就不怎么變了,當(dāng)時(shí)猜測(cè)可能是被壓縮了,查資料(MacOS有使用內(nèi)存壓縮技術(shù))和代碼,發(fā)現(xiàn)iOS還有task_vm_info 這個(gè)結(jié)構(gòu)體,里面剛好有compress這項(xiàng)。
?
然后增加compress這項(xiàng)數(shù)值的輸出,重新測(cè)試!
?
在內(nèi)存使用持續(xù)增加過(guò)程中,游戲賬號(hào)購(gòu)買(mǎi)平臺(tái)當(dāng)resident_size(物理內(nèi)存)不再增加時(shí),compress這項(xiàng)線性增長(zhǎng)。
三、推論
由圖可以看出:實(shí)際內(nèi)存使用 = resident + compress。由此可以認(rèn)為iOS通過(guò)壓縮內(nèi)存來(lái)減少內(nèi)存占用。
并且在測(cè)試過(guò)程中,發(fā)現(xiàn)當(dāng)實(shí)際使用內(nèi)存達(dá)到系統(tǒng)物理內(nèi)存一半時(shí),系統(tǒng)會(huì)不斷發(fā)送memorywarning的警告,達(dá)到60%時(shí)就會(huì)Q掉App。
四、應(yīng)用
現(xiàn)在只需要實(shí)時(shí)拿到task_vm_info里的resident 和 compress 就可以統(tǒng)計(jì)App的實(shí)際內(nèi)存的使用量了,對(duì)于Unity手機(jī)項(xiàng)目來(lái)說(shuō),需要寫(xiě)Native和C#代碼,幸運(yùn)的是,我已經(jīng)幫你把代碼寫(xiě)好了。
在XCodePostProcess::OnPostProcessBuild()里加入如下代碼,會(huì)在Unity生成的XCode工程自動(dòng)插入如下Native代碼:
? ?? ???if( AppRender != null)
? ?? ???{
? ?? ?? ?? ?string TCode = "";
? ?? ?? ?? ?TCode +=? ?"#include <mach/mach_time.h>\n";
? ?? ?? ?? ?TCode +=? ?"#include <mach/mach.h>\n";
? ?? ?? ?? ?TCode +=? ?"#include <mach/mach_host.h>\n";
? ?? ?? ?? ?TCode +=? ?"#include <mach/task_info.h>\n";
? ?? ?? ?? ?TCode +=? ?"#include <mach/task.h>\n";
? ?? ?? ?? ?TCode +=? ?"static float GetTotalPhysicsMemory( )\n";
? ?? ?? ?? ?TCode +=? ?"{\n";
? ?? ?? ?? ?TCode +=? ?"? ? kern_return_t kr;\n";
? ?? ?? ?? ?TCode +=? ?"? ? mach_msg_type_number_t info_count = TASK_VM_INFO_COUNT;\n";
? ?? ?? ?? ?TCode +=? ?"? ? task_vm_info_data_t vm_info;\n";
? ?? ?? ?? ?TCode +=? ?"? ? kr = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t)&vm_info, &info_count);\n";
? ?? ?? ?? ?TCode +=? ?"? ? if (kr == KERN_SUCCESS) return (float)(vm_info.compressed??+ vm_info.resident_size) / 1024.0 / 1024.0;\n";
? ?? ?? ?? ?TCode +=? ?"? ? return 0;\n";
? ?? ?? ?? ?TCode +=? ?"}\n";
? ?? ?? ?? ?TCode +=? ?"extern \"C\" float _Get_Profiler_TotalPhysicMemory(){return _fLockStepPhysicMemory;}\n";
? ?? ?? ?? ?TCode +=? ?"extern \"C\" void UnityRepaint()";
? ?? ?? ?? ?AppRender.Replace("extern \"C\" void UnityRepaint()",TCode );
? ?? ???}
在UnityC#里加入以下托管代碼,調(diào)用 Get_Profiler_TotalPhysicMemory()即可實(shí)時(shí)拿到內(nèi)存使用值。
?
? ? [DllImport("__Internal")]
? ? static extern float _Get_Profiler_TotalPhysicMemory( );
? ? public static float Get_Profiler_TotalPhysicMemory( )
? ? {
? ?? ???return _Get_Profiler_TotalPhysicMemory( );
? ? }
#endif
五、補(bǔ)充
由于系統(tǒng)有分頁(yè)機(jī)制,即你申請(qǐng)使用1字節(jié)的內(nèi)存,系統(tǒng)也有可能會(huì)給你一整頁(yè)(16k大小的物理頁(yè)),所以會(huì)導(dǎo)致這里的實(shí)際內(nèi)存使用量(內(nèi)存分頁(yè)總和)與XCode內(nèi)存統(tǒng)計(jì)(精確統(tǒng)計(jì))不完成相等,但大致符合一定比例。
關(guān)于騰訊游戲?qū)W院專(zhuān)家團(tuán)
如果你的游戲也富有想法充滿(mǎn)創(chuàng)意,如果你的團(tuán)隊(duì)現(xiàn)在也遇到了一些開(kāi)發(fā)瓶頸,那么歡迎你來(lái)聯(lián)系我們。騰訊游戲?qū)W院聚集了騰訊及行業(yè)內(nèi)策劃、美術(shù)、程序等領(lǐng)域的游戲?qū)<?#xff0c;我們將為全世界的創(chuàng)意游戲團(tuán)隊(duì)提供專(zhuān)業(yè)的技術(shù)指導(dǎo)和游戲調(diào)優(yōu)建議,解決團(tuán)隊(duì)在開(kāi)發(fā)過(guò)程中遇到的一系列問(wèn)題。
總結(jié)
以上是生活随笔為你收集整理的如何让手游内存占用更小?从内存消耗iOS实时统计开始的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 腾讯云为小游戏开发者升级工具箱 小游戏联
- 下一篇: 动作游戏老是卡?试试从这些方面提升流畅度