为什么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. MySQL操作之DCL

    目录 SQL语句的分类 DCL语句 SQL语句的分类 DDL(Data Definition Languages)语句:数据定义语言.这些语句定义了不同的数据段. 数据库.表.列.索引等数据库对象的定 ...

  2. 使用Vue.js 和Chart.js制作绚丽多彩的图表

    前言 深入学习 chart.js 的选项来制作漂亮的图表.交互式图表可以给你的数据可视化提供很酷的展示方式.但是大多数开箱即用的解决方案用默认的选项并不能做出很绚丽的图表. 这篇文章中,我会教你如何自 ...

  3. A. Optimal Currency Exchange 兑换硬币,剩下的钱最少

    A. Optimal Currency Exchange time limit per test 1.5 seconds memory limit per test 512 megabytes inp ...

  4. 【剑指Offer面试编程题】题目1510:替换空格--九度OJ

    题目描述: 请实现一个函数,将一个字符串中的空格替换成"%20".例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 输入: 每个 ...

  5. Python字符串(一)

    一.get char 1.获取单个字符 字符串中的每一个字符都会对应一个唯一的下标(索引)用来表示字符串中的位置.下标从0开始依次增加:0对应的是第一个字符:也可以从从-1开始依次减小,-1代表最后一 ...

  6. 5G风口之下,NFV为何发展迅速

    导读 5G高带宽.低时延.大容量的接入方式,注定它一定要依赖于跟以往完全不同的专业设备模式来实现,因此也创造了更多的方向和机会.NFV就是其中之一. 5G最大的变化在网络层面,需要底层网络架构形成一种 ...

  7. 如何反编译MIPS64伪代码?用Ghidra

    在分析固件时,碰到MIPS64架构的程序会很头疼,虽然用IDA能够反编译出汇编代码,但是没办法F5一键反编译成伪代码,如果单看汇编,看久了脑壳痛. 后来Google到了一个好工具,Ghidra,发音和 ...

  8. English-Names

    English-Names 1. 西方姓名的组成 2. 职业姓氏 3. 更多相关链接 中国的姓名,姓氏在前,名子在后.传统也有中间字(世代字).名子非常多.所谓百家姓,姓氏数量有限,约500个左右. ...

  9. Day10 - D - 矿场搭建 HYSBZ - 2730

    煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之后,其他挖 ...

  10. 102、Java中String类之相等判断(忽略大小写)

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...