mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 04:17:17 +00:00
docs: charles jar package
This commit is contained in:
@@ -659,17 +659,29 @@ for (int i = 0; i < threadCount; i++) {
|
||||
|
||||
## 四、App 占有内存
|
||||
|
||||
#### 1. 基础知识回顾
|
||||
硬盘:也叫做磁盘,用于存储数。你存储的歌曲、图片、视频都是在硬盘里。
|
||||
#### 1. 基础知识准备
|
||||
|
||||
内存:由于硬盘读取速度较慢,如果 CPU 运行程序期间,所有的数据都直接从硬盘中读取,则非常影响效率。所以 CPU 会将程序运行所需要的数据从硬盘中读取到内存中。然后 CPU 与内存中的数据进行计算、交换。内存是易失性存储器(断电后,数据消失)。内存条区是计算机内部(在主板上)的一些存储器,用来保存 CPU 运算的中间数据和结果。内存条是程序与 CPU 之间的桥梁。从硬盘读取出数据或者运行程序提供给 CPU。
|
||||
硬盘:也叫做磁盘,用于存储数据。你存储的歌曲、图片、视频都是在硬盘里。
|
||||
|
||||
内存:由于硬盘读取速度较慢,如果 CPU 运行程序期间,所有的数据都直接从硬盘中读取,则非常影响效率。所以 CPU 会将程序运行所需要的数据从硬盘中读取到内存中。然后 CPU 与内存中的数据进行计算、交换。内存是易失性存储器(断电后,数据消失)。内存条区是计算机内部(在主板上)的一些存储器,用来保存 CPU 运算的中间数据和结果。内存是程序与 CPU 之间的桥梁。从硬盘读取出数据或者运行程序提供给 CPU。
|
||||
|
||||
**虚拟内存** 是计算机系统内存管理的一种技术。它使得程序认为它拥有连续的可用内存,而实际上,它通常被分割成多个物理内存碎片,可能部分暂时存储在外部磁盘(硬盘)存储器上(当需要使用时则用硬盘中数据交换到内存中)。Windows 系统中称为 “虚拟内存”,Linux/Unix 系统中称为 ”交换空间“。
|
||||
|
||||
|
||||
|
||||
**虚拟内存** 是计算机系统内存管理的一种技术。它使得程序认为它拥有连续的可用内存,而实际上,它通常被分割成多个物理内存碎片,还是部分暂时存储在外部磁盘(硬盘)存储器上(当需要使用时则用硬盘中数据交换到内存中)。Windows 系统中称为 “虚拟内存”,Linux/Unix 系统中称为 ”交换空间“。
|
||||
#### 2. iOS 内存知识
|
||||
|
||||
内存(RAM)与 CPU 一样都是系统中最稀少的资源,也很容易发生竞争,应用内存与性能直接相关。iOS 没有交换空间作为备选资源,所以内存资源尤为重要。
|
||||
|
||||
什么是 OOM?是 out-of-memory 的缩写,字面意思是超过了内存限制。它是由 iOS 的 `Jetsam` 机制造成的一种非主流 Crash,它不能通过 Signal 这种监控方案所捕获。
|
||||
|
||||
什么是 Jetsam 机制?Jetsam 机制可以理解为系统为了控制内存资源过度使用而采用的一种管理机制。Jetsam 是一个独立的进程,每个进程都有一个内存阈值,一旦超过这个内存阈值,Jetsam 会立即杀掉这个进程。
|
||||
|
||||
为什么设计 Jetsam 机制?因为设备的内存是有限的,所以内存资源非常重要。系统进程以及其他使用的 App 都会抢占这个资源。由于 iOS 不支持交换空间,一旦触发低内存事件,Jetsam 就会尽可能多的释放 App 所在内存,这样 iOS 系统上出现内存不足时,App 就会被系统杀掉,变现为 crash。
|
||||
|
||||
iOS 不支持交换空间?不只是 iOS 不支持交换空间,大多数手机系统都不支持。因为移动设备的大量存储器是**闪存**,它的读写速度远远小电脑所使用的硬盘,也就是说手机即使使用了**交换空间**技术,也因为闪存慢的问题,不能提升性能,所以索性就没有交换空间技术。
|
||||
|
||||
|
||||
内存过大的几种情况
|
||||
|
||||
- App 内存消耗较低,同时其他 App 内存管理也很棒,那么即使切换到其他 App,我们自己的 App 依旧是“活着”的,保留了用户状态。体验好
|
||||
@@ -677,6 +689,41 @@ for (int i = 0; i < threadCount; i++) {
|
||||
- App 内存消耗较大,切换到其他 App 后,即使其他 App 向系统申请的内存不大,系统也会因为内存资源紧张,优先把内存消耗大的 App 杀死。表现为用户将 App 退出到后台,过会儿再次打开会发现 App 重新加载启动。
|
||||
- App 内存消耗非常大,在前台运行时就被系统杀死,造成闪退。
|
||||
|
||||
App 内存不足时,系统会按照一定策略来腾出更多的空间供使用。比较常见的做法是将一部分优先级低的数据挪到磁盘上,该操作为称为 **page out**。之后再次访问这块数据的时候,系统会负责将它重新搬回到内存中,该操作被称为 **page in**。
|
||||
|
||||
|
||||
|
||||
|
||||
##### 2.1 memory page
|
||||
|
||||
**Memory page** 是内存管理中的最小单位,是系统分配的,可能一个 page 持有多个对象,也可能一个大的对象跨越多个 page。通常它是 16KB 大小,且有3种类型的 page。
|
||||
|
||||

|
||||
|
||||
|
||||
- Clean Memory
|
||||
Clean memory 包括3类:可以 `page out` 的内存、内存映射文件、App 使用到的 framework(每个 framework 都有 _DATA_CONST 段,通常都是 clean 状态,但使用 runtime swizling,那么变为 dirty)。
|
||||
|
||||
一开始分配的 page 都是干净的(堆里面的对象分配除外),我们 App 数据写入时候变为 dirty。从硬盘读进内存的文件,也是只读的、clean page。
|
||||
|
||||

|
||||
|
||||
- Dirty Memory
|
||||
|
||||
Dirty memory 包括4类:被 App 写入过数据的内存、所有堆区分配的对象、图像解码缓冲区、framework(framework 都有 _DATA 段和 _DATA_DIRTY 段,它们的内存都是 dirty)。
|
||||
|
||||
在使用 framework 的过程中会产生 Dirty memory,使用单例或者全局初始化方法有助于帮助减少 Dirty memory(因为单例一旦创建就不销毁,一直在内存中,系统不认为是 Dirty memory)。
|
||||
|
||||

|
||||
|
||||
- Compressed Memory
|
||||
|
||||
由于闪存容量和读写限制,iOS 没有交换空间机制,而是在 iOS7 引入了 **memory compressor**。它是在内存紧张时候能够将最近一段时间未使用过的内存对象,内存压缩器会把对象压缩,释放出更多的 page。在需要时内存压缩器对其解压复用。在节省内存的同时提高了响应速度。
|
||||
|
||||
App 运行内存 = pageNumbers * pageSize。因为 Compressed Memory 属于 Dirty memory。所以 Memory footprint = dirtySize + CompressedSize
|
||||
|
||||
设备不同,内存占用上限不同,App 上限较高,extension 上限较低,超过上限 crash 到 `EXC_RESOURCE_EXCEPTION`。
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user