这篇“Unity的PSS/RSS/USS是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Unity的PSS/RSS/USS是什么”文章吧。
USS = 进程独占的内存
RSS = USS + 共享内存
PSS = USS + 共享内存/共享这段内存的进程数量
所以,由于加上了共享内存,PSS的数值是非常不稳定的,和手机的系统和版本都有关系。由于共享内存还需要除以进程数,它甚至还和你安装的软件,和运行时后台程序的数量相关……
因此,你家随便一台手机测试出来的PSS,和腾讯检测时测出来的PSS很可能不同,也就不能死板地拿腾讯的标准对比。
正确的做法是,准备一个固定的测试环境,然后提交一个版本到腾讯,得出两者PSS的差值。然后以后的本地测试都减去这个固定差值就行。
或者,用腾讯本家的游戏作为对比参考,比它们低就行。
腾讯的可以,凭啥你的就不行呢?
当一个进程被杀掉后,释放出来的内存量是USS。
应用本身主动申请的所有内存,堆/栈/纹理数据等等都属于private dirty,也就是USS。共享内存并不是公共库这样的概念,你使用公共库,在公共库的范围创建了新的对象,那部分对象依然属于USS。
共享内存在内存分配上有点类似“静态数据”或者“代码”,应用对它只能读取而不能写入。想要写入就必须先复制一份到USS。所以按我们常规的对“内存分配”的理解,USS就是单个进程占用的内存的全部。
所以,用USS来判断一个应用的内存占用才是科学的。我认为,PSS多出来的“share dirty / progress number”部分根本毫无意义。
安卓的任务管理器显示的应用内存占用就是PSS。并不确定系统是否是以它作为管理基准。
USS在非Root的情况下,不能由外部进程获得。有可能是当初为了检测方便。
很多事情并没有什么“为什么”,你只能接受。而且在孤立环境下PSS检测确实问题不大,因为同一引擎同一时期开发的游戏,PSS比USS多出来的部分“大概”是个固定值,标准相应加上这个固定值就好了。
虽然控制内存的时候大部分情况用Unity自己的Profiler就行了——
但Unity确实不会统计所有的内存占用。我们可以确定,所有额外引入的C代码库它们自己申请的非托管内存都不会计算在内,其中就包括lua。另外,平台渠道的架包它们自己申请的内存也不会计算在内。
如果只是自己控制内存的话,只看Unity的Profiler和Lua单独的内存统计差不多就够了。但是像渠道代码,语音库这类东西,虽然我们对它们无能为力,毕竟是捆绑在一起的,必须给它们挪出相应内存的空闲来,所以我们依然必须关心整个应用的内存占用(但Unity Profiler的结果同样要关心,因为它才是普适的)
而比起用adb查看,能够通过游戏界面呈现出来显然更加便利。
应用内部获得内存数据的办法是 Debug.getMemoryInfo。
Debug.MemoryInfo localMemoryInfo = new Debug.MemoryInfo(); Debug.getMemoryInfo(localMemoryInfo); localMemoryInfo.getTotalPss(); localMemoryInfo.getTotalPrivateDirty();//USS
不编程的话,可以用adb工具查看
adb shell dumpsys meminfo 进程名
(注意结果里privte dirty就是USS)
主要是Debug时用来参考。考虑到运行效率,发布版本最好关闭这个功能。
但……它也可以帮助大家确保通过平台PSS上限的检测。与其担心偶尔超过规定的PSS上限而畏手畏脚降低资源数量,不如放开手,然后在即将到达PSS上限的时候强行回收内存。实在不够的时候,甚至可以禁止新资源加载,用空白物体取代,只保证游戏逻辑可以持续下去。
虽然这里只是为了应付检测,但在实际游戏运行中,如果确实出现了内存不足的情况,这种“放弃游戏体验”的做法也不失为一个办法,毕竟总比应用崩掉要好。
获取PSS/USS的数值并不能帮助我们做到这点。
——因为操作系统并不会因为一个进程占用了固定数量的内存而杀掉它(更不要说每个设备的内存总量还不一样),操作系统只会在内存严重不足,也没有后台进程可杀的时候,才会为了保证系统安全而杀掉前台进程。
所以,我们要做的就是在内存确实不够的时候设法降低内存占用,乃至牺牲体验。具体的做法就是:
执行GC
回收资源,删除缓存,删除预加载内容
降低画质级别
以上皆无效,拒绝新资源的加载
要求用户重启应用
执行时机:
一个办法是实时获取当前系统剩余内存并处理
MemoryInfo:
availMem 当前系统剩余内存
threshold “低内存”的标准
lowMemory 当availMem<threshold即为true,这时候系统会开始关闭后台应用
这段逻辑也可以用来验证回收资源的成果,判断是否要使用更激进的做法。
接受系统发出的内存警告提示
安卓:
onTrimMemory(int state)
当进程在前台时,state的值可能是以下三个
TRIM_MEMORY_RUNNING_CRITICAL:内存不足(后台进程不足3个)
TRIM_MEMORY_RUNNING_LOW:内存不足(后台进程不足5个)
TRIM_MEMORY_RUNNING_MODERATE:内存不足(后台进程超过5个)
这个事件触发比较早,操作系统还可以关闭后台进程来周转。只是提醒在用户内存的紧迫程度。
onLowMemory()
在所有后台进程关闭后,同时处于lowMemory状态时触发。这时候系统已没有内存腾挪的空间。剩余内存继续变少,前台应用随时可能被关闭,以保障操作系统的正常运行(否则只能死机)
IOS:
- (void)didReceiveMemoryWarning
{
(int)OSMemoryNotificationCurrentLevel());
}
OSMemoryNotificationCurrentLevel()的枚举:
OSMemoryNotificationLevelAny = -1 正常
OSMemoryNotificationLevelNormal = 0 正常
OSMemoryNotificationLevelWarning = 1 内存不足警告
OSMemoryNotificationLevelUrgent = 2 严重内存不足警告
OSMemoryNotificationLevelCritical = 3 闪退(所以实际上无法收到此消息)
OSMemoryNotificationLevelWarning可以认为等效onTrimMemory(TRIM_MEMORY_RUNNING_CRITICAL),只是提示出现内存不足的现象,这时候会通过关闭后台进程来获取额外内存,并不一定非要处理。
OSMemoryNotificationLevelUrgent 可以认为等效onLowMemory,表示系统已经处于非常危险的状态,前台进程随时都可能被关闭。
在Unity 5.6之后,提供了系统事件Application.lowMemory,相当于:
- iOS: [UIApplicationDelegate applicationDidReceiveMemoryWarning]
- Android: onLowMemory() and onTrimMemory(level == TRIM_MEMORY_RUNNING_CRITICAL)
当内存出现警告时,并不代表必须要马上执行缩减内存的操作,因为这些操作都是有代价的,仅仅是频繁地GC就会导致游戏体验的极大下降,而这是有可能在不闪退的前提下避免的。
系统给出的内存不足提示本身是为App准备的,如果你在浏览网页过程中弹出了支付宝,显然,你并不希望在支付宝运行过程中把网页的进程杀掉。当内存不足,网页进程要被杀掉前,系统就会给支付宝发一个提示,希望它也能停止申请内存,以便给网页进程保活。
从App的角度,每个应用都应该尽可能共存,内存警告系统也是这样设计的。但是游戏则不同。对于玩家而言,进入游戏把后台的网页杀掉不仅没有关系,也是预期会发生的事。毕竟现在也不兴玩游戏前“清除内存加速球”之类的玩意儿了。
我进游戏前开了几个应用,我没有强关他们,然后我进游戏,游戏为了不杀掉他们却要强行缩减自己的内存降低画质让游戏变卡??
这不是自找没趣么?
不过,从实际结果来看,当到了OSMemoryNotificationLevelWarning,onTrimMemory(level == TRIM_MEMORY_RUNNING_CRITICAL),也就是Unity的Application.lowMemory的触发点的时候,应用确实已经处于较为危险的地步。虽然游戏还可以正常运行,后台进程大多已经关闭,切回桌面也需要重新启动,甚至来个电话收个短信都可能导致游戏被关闭。虽然可能不至于闪退,体验已经变得不好。
个人建议,这个提示出现后只进行对体验影响较小的处理。
如果连续出现,则加大处理的力度。
但如果连onLowMemory,OSMemoryNotificationLevelUrgent都已经被触发了,则必须不计一切代价将内存降低下去,不处理是真的要完蛋的。
此外,onLowMemory,OSMemoryNotificationLevelUrgent在内存申请较快的情况是可能不出现便直接闪退的,它们并不保险。这点在场景加载过程极易发生,所以在加载过程时对内存警告的处理就要更加保守。而在内存较为平稳的阶段,就可以稍微倦怠一些,等待onLowMemory出现后再处理。
然而这些做法其实无异于在刀尖上跳舞,可以的话,还是要尽力将内存降低下去,应用切换的体验也是有必要保证的。切出游戏便无法回来,玩家的体验并不好。
然而如果有平台的PSS限制的话……因为他们的限制往往过于求稳,出现Application.lowMemory(甚至在之前)恐怕就必须清理内存才能满足他们的要求,也就不用考虑那么多了。
以上就是关于“Unity的PSS/RSS/USS是什么”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。