核心问题: Android 15 将默认页面大小从 4KB 提升至 16KB,以优化内存性能。但这会导致使用 C/C++ 代码 (Native 代码) 的应用很可能崩溃,除非重新编译并适配 16K 页面大小。
原因:
-
Linux 内核限制: Android 基于 Linux 内核,而 Linux 不支持混合页面大小。
-
CPU 运行模式: CPU 运行时页面大小是全局设置,要么是 4K,要么是 16K,无法混用。
影响:
-
正面影响: 提升系统内存性能,缩短应用启动时间,降低功耗,加快相机启动速度等。
-
负面影响: 使用了 .so 动态库的应用需重新编译才能兼容,否则大概率崩溃。
如何检测:
-
使用 Android Studio Koala Canary 5 及以上版本。
-
下载并运行 VanillaIceCream 的 16k Page Size 模拟器镜像。
-
通过以下命令查看页面大小是否为 16384。
adb shell getconf PAGE_SIZE
适配方案:
-
升级 NDK 至 r27 或以上版本,并在 Application.mk 中配置
APP_SUPPORT_FLEXIBLE_PAGE_SIZES := true
-
对于 NDK r26 及以下版本,需在 Android.mk 中添加
LOCAL_LDFLAGS += "-Wl,-z,max-page-size=16384"
-
升级 AGP 至 8.3 或以上版本。如果无法升级,则在 packagingOptions 中设置 useLegacyPackaging true 使用压缩共享库。
-
修改代码中硬编码 4096 或使用 mmap 等可能存在问题的代码。
挑战:
-
老旧的 .so 库没有源码,无法重新编译适配。
-
Google Play 计划强制要求应用支持 16K 设备。
总结:
-
16K Page Size 适配对 Android 开发者来说是一个挑战,特别是对于使用了 Native 代码的应用。
-
开发者需要尽早开始适配工作,以避免应用在未来出现兼容性问题。
16K Page Size 问题拓展
1. 16K Page Size 带来的性能提升具体有哪些?
-
减少 TLB (Translation Lookaside Buffer) 未命中率: TLB 是 CPU 中缓存页面映射关系的缓存,更大的页面大小意味着相同内存空间需要更少的 TLB 项,从而降低 TLB 未命中率,提高内存访问效率。
-
减少页面错误: 更大的页面可以减少程序所需页面数量,从而降低页面错误 (Page Fault) 发生的概率,减少从磁盘加载页面的开销。
-
提升内存碎片化程度: 更大的页面可以减少内存碎片化,提高内存利用率。
2. 16K Page Size 对不同类型应用的影响:
-
内存密集型应用: 例如图像处理、视频编辑、游戏等应用将从更大的页面大小中获益最多,因为它们需要频繁访问大量内存。
-
I/O 密集型应用: 对于 I/O 操作较多的应用,16K Page Size 带来的性能提升可能不明显。
-
小型应用: 对于代码量较小的应用,16K Page Size 带来的性能提升可能不明显,甚至可能因为更大的页面粒度而略微降低性能。
3. 未来发展趋势:
-
硬件支持: 未来更多的设备将支持 16K Page Size,这将成为 Android 系统的默认设置。
-
混合页面大小: 虽然目前 Android 不支持混合页面大小,但未来可能会出现支持 4K 和 16K 页面共存的机制。
-
开发者工具: Android Studio 和 NDK 等开发工具将提供更完善的 16K Page Size 支持,例如更方便的代码检查和适配工具。
4. 其他思考:
-
安全性: 更大的页面大小可能会增加某些安全漏洞的风险,例如内存泄露和代码注入攻击。开发者需要关注相关的安全建议和最佳实践。
-
生态系统: 16K Page Size 的普及需要整个 Android 生态系统的支持,包括芯片厂商、设备制造商、应用开发者等。
总而言之,16K Page Size 是 Android 系统为了提升性能而进行的一次重要升级,开发者需要了解其带来的影响和挑战,并尽早进行适配工作。随着硬件和软件的不断发展,16K Page Size 将成为 Android 系统的标配,为用户带来更流畅的体验。