为什么iOS内存使用过多会崩溃,性能会下降?腾讯游戏学院专家Devlin在本文给了解释,如何让手游内存占用更小?从内存消耗iOS实时统计开始。

一、问题

在之前的手游项目中,内存使用过多,都开始崩溃了,所以得做iOS内存统计。内存统计有好几种方法:XCode内存使用统计、UnityInternalProfile内存统计,Mono内存统计等方法。

但是XCode统计需要连手机,UnityInternalProfile的内存统计值与XCode内存统计值差距又太大,崩溃时的内存值跟谁有关系?如何在手机上自己显示内存总量?后面就自己琢磨怎样实现一个适合的内存统计功能。

二、测试研究

研究了下UnityInternalProfile,发现它拿的是mach_base_task_info里的resident_size(物理内存占用)

然后我做了个测试,每几帧分配使用一定大小的内存,然后打印出xcode统计的内存和resident_size。

横坐标是时间,纵坐标是内存。

resident_size值的增长随着内存增长,但增长到一定程度就不怎么变了,当时猜测可能是被压缩了,查资料(MacOS有使用内存压缩技术)和代码,发现iOS还有task_vm_info 这个结构体,里面刚好有compress这项。

然后增加compress这项数值的输出,重新测试!

在内存使用持续增加过程中,当resident_size(物理内存)不再增加时,compress这项线性增长。

三、推论

由图可以看出:实际内存使用 = resident + compress。由此可以认为iOS通过压缩内存来减少内存占用。

并且在测试过程中,发现当实际使用内存达到系统物理内存一半时,系统会不断发送memorywarning的警告,达到60%时就会Q掉App。

四、应用

现在只需要实时拿到task_vm_info里的resident 和 compress 就可以统计App的实际内存的使用量了,对于Unity手机项目来说,需要写Native和C#代码,幸运的是,我已经帮你把代码写好了。

在XCodePostProcess::OnPostProcessBuild()里加入如下代码,会在Unity生成的XCode工程自动插入如下Native代码:

XClass AppRender = new XClass(pathToBuiltProject + "/Classes/UnityAppController+Rendering.mm");
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#里加入以下托管代码,调用 Get_Profiler_TotalPhysicMemory()即可实时拿到内存使用值。

#if ( UNITY_IPHONE && !UNITY_EDITOR )

[DllImport("__Internal")]
static extern float _Get_Profiler_TotalPhysicMemory( );

public static float Get_Profiler_TotalPhysicMemory( )
{
return _Get_Profiler_TotalPhysicMemory( );
}
#endif
(左右滑动可查看全部代码)

五、补充

由于系统有分页机制,即你申请使用1字节的内存,系统也有可能会给你一整页(16k大小的物理页),所以会导致这里的实际内存使用量(内存分页总和)与XCode内存统计(精确统计)不完成相等,但大致符合一定比例。

如何让手游内存占用更小?从内存消耗iOS实时统计开始的更多相关文章

  1. linux服务器内存占用太高-释放内存

    修改/proc/sys/vm/drop_caches,释放Slab占用的cache内存空间(参考drop_caches的官方文档): Writing to this will cause the ke ...

  2. DNF手游公测或将只有安卓版 iOS系统怎么办?

    DNF手游在8月10号确定延期后,目前还不知道新的上线时间.玩家都很关心DNF手游新的公测时间,DNF手游官网的预约数据也是不断突破新高,最终突破了五千万!我们目前拿到的小道消息,DNF手游会在9月1 ...

  3. python垃圾回收,判断内存占用,手动回收内存,二

    以下为例子,判断计算机内存并释放程序内存. # coding=utf8 import time import psutil, gc, commands,os from logger_until imp ...

  4. 绘制FastMM内存分配流程图(小块内存分配)

    http://blog.csdn.net/henreash/article/details/38751353

  5. 知物由学|游戏开发者如何从容应对Unity手游风险?

    本文由  网易云发布. "知物由学"是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理,而后才有智慧,不去求问就不 ...

  6. 年度游戏圈2018白皮书解析手游折扣app哪个好及靠谱程度分析

    2018年,随着全国暂停游戏版本的审核和发布<综合防控儿童青少年近视实施方案>(控制新的在线游戏数量),游戏行业受到的影响不小. 在游戏产业中,游戏行业2018年的收入同比增长5.2%,远 ...

  7. 《疯狂iOS讲义(下)——iPhone/iPad高级应用与手游开发(含CD光盘1张)》

    <疯狂iOS讲义(下)——iPhone/iPad高级应用与手游开发(含CD光盘1张)> 基本信息 作者: 李刚    肖文吉 出版社:电子工业出版社 ISBN:9787121224379 ...

  8. Code Helper占用大量CPU和内存

    项目架构: React+TS+DVA 设备及软件: 设备:Mac 软件:VSCode 场景: 在Mac中使用VSCode运行时发现项目编译非常卡顿,时间长达五六分钟以上,并且项目启动后访问页面,页面也 ...

  9. 『Spring Boot 2.4新特性』减少95%内存占用

    节省 95%的内存占用,减少 80%的启动耗时. GraalVM 是一种高性能的虚拟机,它可以显著的提高程序的性能和运行效率,非常适合微服务.最近比较火的 Java 框架 Quarkus 默认支持 G ...

随机推荐

  1. redis之五大数据类型介绍

    目录 redis五大数据类型 1. string(字符串) 特点: 格式: 基本操作: 2. hash(哈希) 特点: 格式: 基本操作 3. list(列表) 特点 格式 基本操作 4. set(集 ...

  2. python之函数名称空间,作用域,嵌套函数

    目录 嵌套函数 定义 名称空间的三大类(只存变量名) 名称空间加载顺序 变量名的查找顺序为 作用域 嵌套函数 定义 函数内部定义的函数,无法在函数外部使用内部定义的函数. def f1(): def ...

  3. ADV-299 宰羊 (java,过了30%)

    问题描述 炫炫回了内蒙,肯定要吃羊肉啦,所有他家要宰羊吃. 炫炫家有N只羊,羊圈排成一排,标号1~N.炫炫每天吃掉一只羊(这食量!其实是放生啦),吃掉的羊的邻居会以为它被放生了,然后又会告诉他们的邻居 ...

  4. json序列化(重要)

    (1)同(2)public JsonResult JsonUserGet() { DataSet ds = Web_User.P_LG_User_Get(nUserId); return Json(J ...

  5. SC.Lab3对于Factory的构建过程(from HIT)

    Factory设计模式基本就是通过传入指定的参数/或者不传入参数,通过Factory的某个方法(为了避免实例化Factory对象,一般方法为静态static),来获取一个对象.这个是Factory用的 ...

  6. ajax 'Content-Type': 'multipart/form-data' ->文件上传

    'Content-Type': 'multipart/form-data' :指定传输数据为二进制数据,例如图片.mp3.文件

  7. [*CTF2019]babyflash

    用JPEXS反编译flash.swf得到441张黑白图片和1个mp3文件 软件下载地址:https://github.com/jindrapetrik/jpexs-decompiler/release ...

  8. 无线渗透--wifiphisher之wifi钓鱼获取wifi密码

    本来是想试验一下暴力破解的,但是由于字典太大,跑的时间也比较长,于是使用了钓鱼的方法. 先说一下wifiphisher钓鱼获取wifi密码的原理: wifiphisher对于你在攻击中选定的wifi会 ...

  9. 吴裕雄--天生自然JAVA数据库编程:PrepareStatement

    import java.sql.Connection ; import java.sql.DriverManager ; import java.sql.SQLException ; import j ...

  10. jenkins -- 邮件的配置

    参考博文:https://blog.csdn.net/lykio_881210/article/details/81135769 https://www.jianshu.com/p/29a29ce6e ...