如何增加 iOS APP 虚拟地址空间及内存上限?XNU 内核源码解读

简介: 1. 引言最近一段时间在做钉钉 iOS 内存专项治理,解决内存不足时的 jetsam 事件及 malloc 的异常崩溃。在进程创建时系统会为每个 app 设定内存最大使用上限,内核会维护一个内存阈值优先级列表,当设备内存不足时低优先级的 app 会首先被内核中止进程。在阅读 XNU 内核源码过程中我们发现提供系统了两种能力可以扩展 App 的虚拟地址空间(com.apple.developer.kernel.extended-virtual-addressing)和增加内存使用上限(com.apple.developer.kernel.increased-memory-limit)。

每个 App 进程都有自己的虚拟地址空间,在 32 位系统时,虚拟地址空间为 4G,按一般理解 64 位系统虚拟内存地址不受限制的,但通过阅读 XNU 代码发现虚拟地址空间和设备有关联,不同的设备虚拟地址空间是不一样的。当 App 开启"com.apple.developer.kernel.extended-virtual-addressing"这个 entitlement 能力后,内核会增加 App 的虚拟地址空间,使用这个能力 App 可以获得更大的地址空间,解决业务需要申请大的虚拟地址分配导致的崩溃异常。苹果官方解释如下:

“A Boolean value that indicates whether the app may access an extended address space.


Use this entitlement if your app has specific needs that require a larger addressable space. For example, games that memory map assets to stream to the GPU may benefit from a larger address space”

2.1 方案

如何开启这个能力呢?需要在 App entitlement 文件里增加 “com.apple.developer.kernel.extended-virtual-addressing” 的配置,设置 value 的值为 True,同时需要更新证书。

2.2 数据验证

我们通过测试代码来验证下开启 “com.apple.developer.kernel.extended-virtual-addressing” 和未开启时的数据对比。由于是增加虚拟内存地址空间,我们尝试无限分配大内存但不 Dirty 数据试试,每次循环分配 1M 内存,直到无法分配内存地址,最后统计分配的内存数据大小。部分代码如下

image.png

从测试数据上惊奇发现未开启地址空间是 2G,开启后达到 54G,开启后内核会为 App 扩展足够使用的虚拟地址空间。

2.3 内核源码分析

通过分析 XNU 内核源码,我们发现如果开启 “com.apple.developer.kernel.extended-virtual-addressing” 能力后,内核会开启一种称之为 “jumbo” 模式。未开启 “jumbo” 模式时不同的设备虚拟地址空间是不一样的,虚拟地址空间和设备有关联,当开启后在 iOS14 以上设备虚拟地址空间会达到 64G。整体数据如下列表:

image.png

2.3.2 jumbo 模式申请地址空间

64 位通过 pmap_max_64bit_offset 这个接口来申请虚拟地址空间,如果开启“jumbo”模式,这个接口参数 option 的值是 ARM_PMAP_MAX_OFFSET_JUMBO,如果未开启 option 的值是 ARM_PMAP_MAX_OFFSET_DEVICE,通过代码发现 ARM_PMAP_MAX_OFFSET_DEVICE 选项在不同的设备的空间是不一样的。部分核心代码如下:

image.png在进程创建时,系统会为 App 指定默认的内存上限,在 App 运行过程中分配的内存超过内核指定的内存上限时,内核会触发 jetsam 机制主动中止当前进程。在研究 XNU 内核代码过程中,发现系统提供了三种方式来增加 App 的内存使用上限。如果 App 申请了“com.apple.developer.kernel.increased-memory-limit” entitlement 配置能力后,内核会增加 App 的内存上限。当 App 分配的内存超过系统默认的内存上限后,App 仍然可以继续很好的运行。相对于未申请该能力的其他进程,拥有该能力的 App 有了更高内存使用优先级。苹果官网解释如下:

“A Boolean value that indicates whether core features of your app may perform better with a higher memory limit on supported devices.


Add this entitlement to your app to inform the system that some of your app’s core features may perform better by exceeding the default app memory limit on supported devices. If you use this entitlement, make sure your app still behaves correctly if additional memory isn’t available”。

3.1 方案

苹果提供了如下三种方式来主动增加 App 的内存上限。主动申请增加内存上限需要在 entitlement 里增加配置能力,三种方案各有不同的策略,而且有些方案是内核私有能力。三种方案对比如下:

image.png

通过测试发现,开启增加内存上限 entitlement 后,相比未开启内存分配的数据会略微增加。

3.3 内核源码分析

3.3.1 内存告警计算

进程 task 初始化时会解析启动的入参“max_task_pmem”,读取 app 最大的内存限制。App 内存最大限制及告警阈值和设备内存的大小有关联,当 App 使用内存超过最大内存限制的 80%时会发出 warning 初步告警。计算列表如下:

image.png

3.3.2 能力开启

App 进程创建时通过判断 Entitlement 是否开启 “com.apple.developer.kernel.increased-memory-limit” 配置能力,如果开启后通过 “memorystatus_act_on_entitled_task_limit” 方法来增加内存上限。核心代码如下:

image.png

4. 总结

通过内核探索我们初步了解了系统在虚拟地址空间和内存分配上限的运行逻辑,申请两种能力后 App 可以申请更多的虚拟地址空间和内存上限。开启 “jumbo” 模式 可以解决一些大地址内存映射地址空间不足导致的异常及崩溃等问题,申请增加内存上限后 App 可以获得更多的内存分配优先权,App 运行会更加流畅。

5. 参考



相关文章
|
3月前
|
存储 开发框架 .NET
"揭秘.NET内存奥秘:从CIL深处窥探值类型与引用类型的生死较量,一场关于速度与空间的激情大戏!"
【8月更文挑战第16天】在.NET框架中,通过CIL(公共中间语言)可以深入了解值类型与引用类型的内存分配机制。值类型如`int`和`double`直接在方法调用堆栈上分配,访问迅速,生命周期随栈帧销毁而结束。引用类型如`string`在托管堆上分配,堆栈上仅存储引用,CLR负责垃圾回收,确保高效且自动化的内存管理。
56 6
|
18天前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
192 2
|
2月前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
130 5
|
3月前
|
存储 缓存 编译器
Linux源码阅读笔记06-RCU机制和内存优化屏障
Linux源码阅读笔记06-RCU机制和内存优化屏障
|
3月前
|
算法 安全 UED
探索操作系统的内核空间:虚拟内存管理
【7月更文挑战第50天】 在现代操作系统中,虚拟内存管理是核心功能之一,它允许操作系统高效地使用物理内存,并为应用程序提供独立的地址空间。本文将深入探讨操作系统虚拟内存管理的机制,包括分页、分段以及内存交换等关键技术,并分析它们如何共同作用以实现内存的有效管理和保护。通过理解这些原理,读者可以更好地把握操作系统的内部工作原理及其对应用程序性能的影响。
|
3月前
|
iOS开发
App备案与iOS云管理式证书 ,公钥及证书SHA-1指纹的获取方法
App备案与iOS云管理式证书 ,公钥及证书SHA-1指纹的获取方法
185 0
App备案与iOS云管理式证书 ,公钥及证书SHA-1指纹的获取方法
|
3月前
|
Swift iOS开发
iOS开发-属性的内存管理
【8月更文挑战第12天】在iOS开发中,属性的内存管理至关重要,直接影响应用性能与稳定性。主要策略包括:`strong`(强引用),不维持对象生命期,可用于解除循环引用;`assign`(赋值),适用于基本数据类型及非指针对象属性;`copy`,复制对象而非引用,确保对象不变性。iOS采用引用计数管理内存,ARC(自动引用计数)自动处理引用增减,简化开发。为避免循环引用,可利用弱引用或Swift中的`[weak self]`。最佳实践包括:选择恰当的内存管理策略、减少不必要的强引用、及时释放不再使用的对象、注意block内存管理,并使用Xcode工具进行内存分析。
|
3月前
|
Android开发 iOS开发 C#
Xamarin:用C#打造跨平台移动应用的终极利器——从零开始构建你的第一个iOS与Android通用App,体验前所未有的高效与便捷开发之旅
【8月更文挑战第31天】Xamarin 是一个强大的框架,允许开发者使用单一的 C# 代码库构建高性能的原生移动应用,支持 iOS、Android 和 Windows 平台。作为微软的一部分,Xamarin 充分利用了 .NET 框架的强大功能,提供了丰富的 API 和工具集,简化了跨平台移动应用开发。本文通过一个简单的示例应用介绍了如何使用 Xamarin.Forms 快速创建跨平台应用,包括设置开发环境、定义用户界面和实现按钮点击事件处理逻辑。这个示例展示了 Xamarin.Forms 的基本功能,帮助开发者提高开发效率并实现一致的用户体验。
151 0
|
存储 缓存 Go
iOS原理分析之从源码看load与initialize方法(一)
iOS原理分析之从源码看load与initialize方法
242 0
iOS原理分析之从源码看load与initialize方法(一)