温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Unity的PSS/RSS/USS是什么

发布时间:2022-01-11 15:39:11 来源:亿速云 阅读:639 作者:iii 栏目:大数据

这篇“Unity的PSS/RSS/USS是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Unity的PSS/RSS/USS是什么”文章吧。

PSS在不同手机测试的结果是不同的

USS = 进程独占的内存

RSS = USS + 共享内存

PSS = USS + 共享内存/共享这段内存的进程数量

所以,由于加上了共享内存,PSS的数值是非常不稳定的,和手机的系统和版本都有关系。由于共享内存还需要除以进程数,它甚至还和你安装的软件,和运行时后台程序的数量相关……

因此,你家随便一台手机测试出来的PSS,和腾讯检测时测出来的PSS很可能不同,也就不能死板地拿腾讯的标准对比。

正确的做法是,准备一个固定的测试环境,然后提交一个版本到腾讯,得出两者PSS的差值。然后以后的本地测试都减去这个固定差值就行。

或者,用腾讯本家的游戏作为对比参考,比它们低就行。

腾讯的可以,凭啥你的就不行呢?

用PSS判断应用的内存占用科学吗?

当一个进程被杀掉后,释放出来的内存量是USS。

应用本身主动申请的所有内存,堆/栈/纹理数据等等都属于private dirty,也就是USS。共享内存并不是公共库这样的概念,你使用公共库,在公共库的范围创建了新的对象,那部分对象依然属于USS。

共享内存在内存分配上有点类似“静态数据”或者“代码”,应用对它只能读取而不能写入。想要写入就必须先复制一份到USS。所以按我们常规的对“内存分配”的理解,USS就是单个进程占用的内存的全部。

所以,用USS来判断一个应用的内存占用才是科学的。我认为,PSS多出来的“share dirty / progress number”部分根本毫无意义。

PSS看起来这么不科学,为啥要把它当作限制?

  • 安卓的任务管理器显示的应用内存占用就是PSS。并不确定系统是否是以它作为管理基准。

  • USS在非Root的情况下,不能由外部进程获得。有可能是当初为了检测方便。

  • 很多事情并没有什么“为什么”,你只能接受。而且在孤立环境下PSS检测确实问题不大,因为同一引擎同一时期开发的游戏,PSS比USS多出来的部分“大概”是个固定值,标准相应加上这个固定值就好了。

如何获取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)

获取的实时PSS/USS可以用来做什么?

主要是Debug时用来参考。考虑到运行效率,发布版本最好关闭这个功能。

但……它也可以帮助大家确保通过平台PSS上限的检测。与其担心偶尔超过规定的PSS上限而畏手畏脚降低资源数量,不如放开手,然后在即将到达PSS上限的时候强行回收内存。实在不够的时候,甚至可以禁止新资源加载,用空白物体取代,只保证游戏逻辑可以持续下去。

虽然这里只是为了应付检测,但在实际游戏运行中,如果确实出现了内存不足的情况,这种“放弃游戏体验”的做法也不失为一个办法,毕竟总比应用崩掉要好。

如何才能避免我们的应用由于内存不足崩掉?

获取PSS/USS的数值并不能帮助我们做到这点。

——因为操作系统并不会因为一个进程占用了固定数量的内存而杀掉它(更不要说每个设备的内存总量还不一样),操作系统只会在内存严重不足,也没有后台进程可杀的时候,才会为了保证系统安全而杀掉前台进程。

所以,我们要做的就是在内存确实不够的时候设法降低内存占用,乃至牺牲体验。具体的做法就是:

  • 执行GC

  • 回收资源,删除缓存,删除预加载内容

  • 降低画质级别

  • 以上皆无效,拒绝新资源的加载

  • 要求用户重启应用

执行时机:

一个办法是实时获取当前系统剩余内存并处理

Unity的PSS/RSS/USS是什么  
某著名游戏的代码
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是什么”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI