名称来自战争术语 抢滩登陆 (beach head) 目的是更快的将iOS的application启动提速. 让用户更快的打开app !推广一波🤣 开源库
进程访问内存的原理 在计算机中,进程 是操作系统分配给正在运行的程序的一种资源。它可以看作是程序的执行实例,包括程序计数器、寄存器、堆栈和打开的文件等。每个进程都在自己的虚拟地址空间中运行,这使得每个进程都有自己独立的内存空间。
虚拟地址 地址空间划分:操作系统将每个进程的地址空间划分为多个固定大小的页。通常,每个页的大小为4KB
页表创建:操作系统为每个进程创建一个页表,用于将虚拟地址映射到物理地址。页表是一个数据结构,它记录了每个虚拟页对应的物理页的地址。
虚拟地址转换:当进程访问内存时,它使用虚拟地址。操作系统通过查找页表中的映射关系,将虚拟地址转换为物理地址。这个转换过程通常包括两个步骤。
页目录查找:进程的虚拟地址通常被划分为三个部分:页目录索引、页表索引和页内偏移。首先,操作系统使用页目录索引在页目录中查找对应的页表。 页表查找:操作系统使用页表索引在找到的页表中查找对应的物理页的地址 内存访问:当虚拟地址被转换为物理地址后,进程可以使用物理地址来访问内存。这样,进程就可以在自己的虚拟地址空间中进行内存操作,而不需要关心物理内存的实际分布。 为了提高效率和方便管理,又对虚拟内存和物理内存又进行分页(Page)。当进程访问一个虚拟内存 Page 而对应的物理内存却不存在时,会触发一次缺页中断(Page Fault),分配物理内存,有需要的话会从磁盘 mmap 读人数据。 mmap
mmap是一种内存映射技术,它允许应用程序将文件或其他设备映射到自己的虚拟地址空间中,从而可以像访问内存一样访问这些数据。mmap可以提供高效的读写文件的方式,并且还可以用于共享内存和匿名内存映射等场景
Page Fault 当进程访问一个虚拟内存 Page 而对应的物理内存却不存在时,会触发一次缺页中断(Page Fault),分配物理内存,有需要的话会从磁盘 mmap 读人数据。通过 App Store 渠道分发的 App,Page Fault 还会进行签名验证,所以一次 Page Fault 的耗时比想象的多
1.虚拟内存允许操作系统摆脱物理 RAM 的限制。虚拟内存管理器创建一个逻辑地址空间(或“每个进程的“虚拟”地址空间)并将其划分为大小统一的内存块,称为页面。处理器及其内存管理单元(MMU)维护一个页表将程序逻辑地址空间中的页面映射到计算机 RAM 中的硬件地址。当程序代码访问内存中的地址时,MMU 使用页表将指定的逻辑地址转换为实际的硬件内存地址。这种转换是自动发生的,并且对于正在运行的应用程序是透明的。
2.对于程序而言,其逻辑地址空间中的地址始终可用。但是,如果应用程序访问当前不在物理 RAM 中的内存页上的地址,发生页面错误。当这种情况发生时,虚拟内存系统会调用一个特殊的页面错误处理程序来立即响应该错误。页面错误处理程序停止当前正在执行的代码,找到物理内存的空闲页面,从磁盘加载包含所需数据的页面,更新页表,然后将控制权返回给程序代码,程序代码可以访问内存地址通常情况下。这个过程被称为寻呼。
3.如果物理内存中没有可用的空闲页面,则处理程序必须首先释放现有页面以为新页面腾出空间。系统如何发布页面取决于平台。在 OS X 中,虚拟内存系统经常将页面写入后备存储。这后备存储是基于磁盘的存储库,其中包含给定进程使用的内存页的副本。将数据从物理内存移动到后备存储称为调出(或“交换出”);将数据从后备存储移回物理内存称为分页(或“交换”)。在 iOS 中,没有后备存储,因此页面永远不会调出到磁盘,但只读页面仍会根据需要从磁盘调入。
4.在 OS X 和早期版本的 iOS 中,页面的大小是 4 KB。在更高版本的 iOS 中,基于 A7 和 A8 的系统向由 4 KB 物理页支持的 64 位用户空间公开 16 KB 页面,而 A9 系统公开由 16 KB 物理页支持的 16 KB 页面。这些大小决定了发生页面错误时系统从磁盘读取多少KB。当系统花费过多的时间处理页面错误以及读写页面而不是执行程序代码时,就会发生磁盘抖动。
binary
-
Read Article
-
Read Article虽然ARC时代不需要手动管理内存,但是我们仍然要注意循环引用和CoreFoundation对象的引用计数问题… 虽然ARC时代不需要手动管理内存,但是我们仍然要注意循环引用和CoreFoundation对象的引用计数问题 MRC 对象操作 OC中对应的方法 对应的引用计数的化 持有对象 retain +1 释放对象 release -1 废弃对象 dealloc 0 ARC 根据指针来操作引用 在ARC模式下,只要没有强指针(强引用)指向对象,对象就会被释放。在ARC模式下,不允许使用retain、release、retainCount等方法。并且,如果使用dealloc方法时,不允许调用[super dealloc]方法。 ARC模式下的property变量修饰词为strong、weak,相当于MRC模式下的retain、assign。strong :代替retain,缺省关键词,代表强引用。weak:代替assign,声明了一个可以自动设置nil的弱引用,但是比assign多一个功能,指针指向的地址被释放之后,指针本身也会自动被释放。 实现方式是在编译时期自动在已有代码中插入合适的内存管理代码以及在 Runtime 做一些优化。详细的工作原理见 上一篇 内存管理(2) ARC提供四种与内存管理有关的变量标识符,分别是: 关键字 __strong __strong 是默认使用的标识符。只有还有一个强指针指向某个对象,这个对象就会一直存活。 __weak __weak 声明这个引用不会保持被引用对象的存活,如果对象没有强引用了,弱引用会被置为 nil _ unsafe _unretained __unsafe_unretained 声明这个引用不会保持被引用对象的存活,如果对象没有强引用了,它不会被置为 nil。如果它引用的对象被回收掉了,该指针就变成了野指针。 __autoReleasing __autoreleasing 用于标示使用引用传值的参数(id *),在函数返回时会被自动释放掉。 变量标识符的用法如下,在类型和变量名之间: Number* __strong num = [[Number alloc] init]; 属性标识符 @property (assign/retain/strong/weak/unsafe_unretained/copy) Number* num assign表明 setter 仅仅是一个简单的赋值操作,通常用于基本的数值类型,例如CGFloat和NSInteger。 key 含义 strong 表明属性定义一个拥有者关系。当给属性设定一个新值的时候,首先这个值进行 retain ,旧值进行 release ,然后进行赋值操作。 weak 表明属性定义了一个非拥有者关系。当给属性设定一个新值的时候,这个值不会进行 retain,旧值也不会进行 release, 而是进行类似 assign 的操作。不过当属性指向的对象被销毁时,该属性会被置为nil unsafe_unretained 语义和 assign 类似,不过是用于对象类型的,表示一个非拥有(unretained)的,同时也不会在对象被销毁时置为nil的(unsafe)关系 copy 类似于 strong,不过在赋值时进行 copy 操作而不是 retain 操作。通常在需要保留某个不可变对象(NSString最常见),并且防止它被意外改变时使用 unsafe_unretained (1)兼容性,iOS4之前没有weak只能用unsafe_unretained(2)性能考虑,性能比weak要好 ARC下仍然需要注意的内存管理问题 循环引用问题。 当两个对象互相持有对方的强引用时,并且这两个对象的引用计数都不是0的时候,便造成了引用循环,从而使用计数后内存无法得到释放。可以从以下几个方面入手:
-
Read Article经过前面文档我们大致了解了arc/mrc机制,是为了更好的去做iOS的内存管理 前言 经过前面文档我们大致了解了arc/mrc机制,是为了更好的去做iOS的内存管理.在面对一个对象的时候,从初始化到delloc销毁的过程中进行合适的插入 retain 和 release 做到内存的回收释放♻️,随着iOS的迭代发展,我们开始逐渐采用一种解放程序员的新型管理模式 ARC … 什么是ARC/MRC Manual Reference Counting 是根据对象的引用计数器 reference count 来判断在何时将一个对象所占用的内存回收 Automatic Reference Counting 自动引用计数 是苹果子WWDC2011年引入的,其工作原理下面详细理解,根本上是通过强指针来判断 AutoreleasePool 从main函数开始了解: int main(int argc, const char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } 在这个autoreleasepool的block里面 所有的事件,消息,全部转交给了UIApplication来处理,从此可以看出一个iOS应用是完全包裹在自动释放池里面的 通过clang 编译器将main函数转换成了 main.cpp $ clang -rewrite-objc main.m 我们将关注点放在__AtAutoreleasePool这个结构体上面 struct __AtAutoreleasePool { __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();} ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);} void * atautoreleasepoolobj; }; 不难看出我们main函数的工作原理大致上是在初始化时候调用了 void * atautoreleasepoolobj = objc_autoreleasePoolPush(); 然后在析构时候调用了
-
Read Article在iOS的开发中我们接触到了ARC/MRC这些机制,为了更好的了解其中的原理,我们可以从官方的文档作为入口来看看这些名词背后更深入的意义. 在iOS的开发中我们接触到了ARC/MRC这些机制,为了更好的了解其中的原理,我们可以从官方的文档作为入口来看看这些名词背后更深入的意义. 01内存管理 基本内存管理规则内存管理模型基于对象所有权。任何对象都可以具有一个或多个所有者。只要一个对象至少具有一个所有者,它就会继续存在。如果对象没有所有者,则运行时系统会自动销毁它. 苹果给出了四条准则 管理任何由你自己创建的对象 通过retain来持有一个对象 (在对象方法/init方法中调用 )一般在下面两种情况 当你想将一个对象存储为属性值时 当你想防止一个对象被释放时 当你不再需要这个对象时候 请释放 Person *aPerson = [[Person alloc] init]; // ... NSString *name = aPerson.fullName; // ... [aPerson release]; tips 1.在iOS中涉及到对象持有的是基于一套 NSObject protocol协议 以及一些标准的方法名来实现的,例如alloc,newObject,copy,mutableCopy来实现的 2.管理对象,我们从Apple给出的两个例子 当你担心你的对象alloc后,在return之前调用[object release]导致对象被释放 那么采用autorelease,该方法会在返回对象之后调用release方法 - (NSString *)fullName { NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", self.firstName, self.lastName] autorelease]; return string; } 下面这种方法是在调用者调用此方法之后 对象被销毁之前达到将对象传递给外面的效果 - (NSString *)fullName { NSString *string = [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName]; return string; } 我们也可以通过ClassName 或者 id 去完成我们的逻辑操作例如&object指向内存地址 ,所以我们不持有对象就无需去管理对象