【Unity3D】Unity内存解析 (一)

539 阅读4分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路。

前言

之前看的一个Unity官方的视频:浅谈Unity内存管理([Unity 活动]-浅谈Unity内存管理_哔哩哔哩_bilibili);觉得干货满满,但是一时又不能完全记下来,当时就想记个笔记。但是后面要么忘了,要么没时间,一直没有实现(主要还是懒)。

这一次重新看一遍视频,再结合我自己的一些理解,一边学习一边总结。

1、什么是内存

内存分为物理内存、虚拟内存。

关于物理内存:

关于物理内存需要记住:CPU访问内存是一个慢速过程。CPU在需要访问内存时,先是访问自己的缓存(L1Cache、L2Cache……),当全部Miss之后,然后CPU回去主内存拿一段完整的指令到CPU的缓存中。因此,我们需要尽可能保证CPU的指令是连续的,防止CPU过多地与主内存之间的内存交换产生IO。Unity为了处理上述问题,减少Cache Miss ,使用了ECS和DOTS,把分散的内存数据变成整块、连续的数据。

(PS:ECS和DOTS虽然已经实装,但我个人的使用体验来讲还不够成熟,而且API还有可能再改。而且在ECS的部分,似乎热更也是个问题,所以要谨慎使用。)

关于虚拟内存:

电脑在物理内存不够的时候,操作系统会把一些不用的数据(DeadMemory)交换到硬盘上,称之为内存交换。但是手机是不做内存交换的,一是因为移动设备的硬盘IO速度比PC慢很多,而是因为移动设备的硬盘可擦写次数更少;因此手机如果做内存交换一是慢,而是减少设备寿命看,所以Android机上没有做内存交换。IOS可以把不活跃的内存进行压缩,使得实际可用的内存更多,而安卓没有这个能力。

关于移动设备和PC:

移动设备(手机)与PC的区别在于,手机没有独立显卡、独立显存。手机上无论是CPU还是GPU都是共用一个缓存,而且手机的内存更小、缓存级数更少、大小更小。台式机的三级缓存大约8~16M,而手机只有2M。

综上,手机上的内存,不论从哪个角度看,都是比PC要小很多的。所以,手机上更容易出现内存不够的问题。

2、Android 内存管理

Android是基于Linux开发的,所以Android的内存管理和Linux很相似。

Android的内存管理基本单位是Page(页),一般是4k 一个Page。内存的回收和分配都是以 Page为单位进行操作,也就是4k。Android内存分用户态和内核态两个部分,内核态的内存是用户严格不能访问的。

关于内存杀手:Low Memory Killer (LMK)

当手机的内存使用量过多时,就会出现LMK,对当前手机的各种App、服务进行关停。安卓的各种应用、服务分为以下一些类别:

0、Native:系统内核

1、System:系统服务

2、Persistent: 用户服务,比如电话、蓝牙、Wifi等。

3、Foreground:前台应用,当前正在使用的Activity

4、Perceptible:辅助应用,音乐、搜索、键盘等;

5、Service:驻后台线程的服务,云同步、垃圾回收等;

6、Home键;

7、Previous:上一个使用的应用;

8、Cached:后台,之前使用过的各种应用。

这个也是Android系统的应用优先度排序,编号越小优先级越高。当LMK开始工作的时候,会从优先度最低的应用开始Kill。即最先中断各种Cached,最后才会到Native。

例如当Cached被杀掉之后,现象就是当你切换到后台的那些应用时,你会发现那些应用重启了。

当Home被杀死的时候,你发现当你回到桌面时,桌面会重启,你的桌面图标会重建,或者壁纸没了。

到Perceptible的时候,可能你的音乐、键盘不见了。

再往上进行,到Foreground时,当前前台应用就会被杀死,这个时候就会出现应用闪退。

在往上手机就开始重启了。

3、Android内存指标

RSS:Resident Set Size

你当前的APP所应用到的所有内存。除了你自己的APP所使用的内存之外,你调用的各种服务、共用库所产生的内存都会统计到RSS之中。

PSS:Proportional Set Size

与RSS不同的是,PSS会把公共库所使用的内存平摊到所有调用这个库的APP上。(可能你自己的应用没有申请很多内存,但是你的调用的某个公共库已经有了很大的内存分配,平摊下来就会导致你自己的APP的PSS虚高。)

USS:Unique Set Size

只有此APP所使用的内存,剔除掉公共库的内存分配。

我们在实际工作中更多要做的是对USS的优化,有时也会注意一下PSS。