Native开发工具之CPU 和架构(三)(1),android性能优化和内存优化

  • VFP 硬件 FPU 指令。更具体一点,是指 VFPv3-D16,它除了 ARM 核心中的 16 个 32 位寄存器之外,还包含 16 个专用 64 位浮点寄存器。

v7-a ARM 规范描述的其他扩展指令集,包括高级 SIMD(亦称 NEON)、VFPv3-D32 和 ThumbEE,都是此 ABI 的可选扩展指令集。由于不能保证它们存在,因此系统在运行时应检查扩展指令集是否可用。如果不可用,您必须使用替代代码路径。此检查类似于系统在检查或使用 MMXSSE2 及 x86 CPU 上其他专用指令集时所执行的检查。

要了解如何执行这些运行时检查,请参阅 cpufeatures。此外,如需有关 NDK 支持为 NEON 编译机器代码的信息,请参阅 NEON 支持

armeabi-v7a ABI 使用 -mfloat-abi=softfp 开关强制实施以下规则:编译器在函数调用期间必须传递核心寄存器对中的所有双精度值,而不是专用浮点值。系统可以使用 FP 寄存器执行所有内部计算。这样可极大地提高计算速度。

arm64-v8a

此 ABI 适用于基于 ARMv8、支持 AArch64 的 CPU。它还包含 NEON 和 VFPv4 指令集。

如需了解更多信息,请参阅 ARMv8 技术预览,并联系 ARM 进一步了解详情。

x86

此 ABI 适用于支持通常称为“x86”或“IA-32”的指令集的 CPU。此 ABI 的特性包括:

  • 指令一般由具有编译器标记的 GCC 生成,如下所示:

-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32

这些标记指向 Pentium Pro 指令集,以及 MMXSSESSE2SSE3SSSE3 扩展指令集。生成的代码在顶层 Intel 32 位 CPU 之间进行了均衡优化。

如需了解有关编译器标记的更多信息,特别是与性能优化相关的信息,请参阅 GCC x86 性能提示

ABI 不含任何其他可选 IA-32 扩展指令集,例如:

  • MOVBE

  • SSE4 的任何变体。

您仍可使用这些扩展指令集,只要您使用运行时功能探测来启用它们,并且为不支持它们的设备提供回退机制。

NDK 工具链假设在函数调用之前进行 16 字节堆栈对齐。默认工具和选项会强制实施此规则。如果编写的是汇编代码,必须确保堆栈对齐,而且其他编译器也遵守此规则。

请参阅以下文档了解更多详情:

x86_64

此 ABI 适用于支持通常称为“x86-64”的指令集的 CPU。它支持 GCC 通常使用以下编译器标记生成的指令:

-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel

这些标记指向 x86-64 指令集(根据 GCC 文档),以及 MMXSSESSE2SSE3SSSE3SSE4.1SSE4.2POPCNT 扩展指令集。生成的代码在顶层 Intel 64 位 CPU 之间进行了均衡优化。

如需了解有关编译器标记的更多信息,特别是与性能优化相关的信息,请参阅 GCC x86 性能

此 ABI 不含任何其他可选的 x86-64 扩展指令集,例如:

  • MOVBE

  • SHA

  • AVX

  • AVX2

您仍可使用这些扩展指令集,只要您使用运行时功能探测来启用它们,并且为不支持它们的设备提供回退机制。

请参阅以下文档了解更多详情:

为特定 ABI 生成代码

默认情况下,NDK 指向所有非弃用 ABI。您可通过在 Application.mk 文件中设置 APP_ABI 来指向单个 ABI。以下代码段演示了使用 APP_ABI 的几个示例

APP_ABI := arm64-v8a # Target only arm64-v8a

APP_ABI := all # Target all ABIs, including those that are deprecated.

APP_ABI := armeabi-v7a x86_64 # Target only armeabi-v7a and x86_64.

要详细了解您可以为 APP_ABI 变量指定的值,请参阅 Android.mk

编译系统的默认行为是将每个 ABI 的二进制文件包括在单个 APK(也称为胖 APK)内。与仅包含单个 ABI 的二进制文件的 APK 相比,胖 APK 要大得多;要权衡的是兼容性更广,但 APK 更大。强烈建议您利用拆分 APK 减小 APK 的大小,同时仍保持最大限度的设备兼容性。

在安装时,软件包管理器只解压缩最适合目标设备的机器代码。详情请参阅安装时自动解压缩原生代码

Android 平台上的 ABI 管理

本部分详细说明了 Android 平台如何管理 APK 中的原生代码。

应用软件包中的原生代码

Play 商店和软件包管理器都希望能在 APK 中符合以下格式的文件路径上找到 NDK 生成的库:

/lib//lib.so

其中,<abi>支持的 ABI 下列出的 ABI 名称之一,<name> 是您为 Android.mk 文件中的 LOCAL_MODULE 变量定义库时使用的库名称。由于 APK 文件只是 zip 文件,因此打开它们并确认共享原生库位于该位于的位置很简单。

如果系统在预期位置找不到原生共享库,便无法使用它们。在这种情况下,应用本身必须复制这些库,然后执行 dlopen()

在胖 APK 中,每个库位于名称与相应 ABI 匹配的目录下。例如,胖 APK 可能包含:

/lib/armeabi/libfoo.so

/lib/armeabi-v7a/libfoo.so

/lib/arm64-v8a/libfoo.so

/lib/x86/libfoo.so

/lib/x86_64/libfoo.so

注意:搭载 4.0.3 或更早版本、基于 ARMv7 的 Android 设备从 armeabi 目录(而非 armeabi-v7a 目录,如果两个目录都存在)安装原生库。这是因为在 APK 中,/lib/armeabi//lib/armeabi-v7a/ 后面。从 4.0.4 开始,此问题已修复。

Android 平台 ABI 支持

Android 系统在运行时知道它支持哪些 ABI,因为版本特定的系统属性会指示:

  • 设备的主要 ABI,与系统映像本身使用的机器代码对应。

  • (可选)与系统映像也支持的其他 ABI 对应的辅助 ABI。

此机制确保系统在安装时从软件包提取最佳机器代码。

为实现最佳性能,应直接针对主要 ABI 进行编译。例如,基于 ARMv5TE 的典型设备只会定义主要 ABI:armeabi。相反,基于 ARMv7 的典型设备将主要 ABI 定义为 armeabi-v7a,并将辅助 ABI 定义为 armeabi,因为它可以运行为每个 ABI 生成的应用原生二进制文件。

64 位设备也支持其 32 位变体。以 arm64-v8a 设备为例,该设备也可以运行 armeabi 和 armeabi-v7a 代码。但请注意,如果应用以 arm64-v8a 为目标,而非依赖于运行 armeabi-v7a 版应用的设备,应用在 64 位设备上的性能要好得多。

许多基于 x86 的设备也可运行 armeabi-v7aarmeabi NDK 二进制文件。对于这些设备,主要 ABI 将是 x86,辅助 ABI 是 armeabi-v7a

安装时自动解压缩原生代码

安装应用时,软件包管理器服务将扫描 APK,并查找以下形式的任何共享库:

lib//lib.so

如果未找到,并且您已定义辅助 ABI,该服务将扫描以下形式的共享库:

lib//lib.so

找到所需的库时,软件包管理器会将它们复制到应用的 data 目录 (data/data/<package_name>/lib/) 下的 /lib/lib<name>.so

如果根本没有共享对象文件,应用也会编译并安装,但在运行时会崩溃。

三、处理CPU功能

=========

ABI:使用预处理器的预定义宏

通常,在编译时使用 #ifdef 及以下各项确定 ABI 最为方便:

  • 对于 32 位 ARM,使用 __arm__

  • 对于 64 位 ARM,使用 __aarch64__

  • 对于 32 位 X86,使用 __i386__

  • 对于 64 位 X86,使用 __x86_64__

请注意:32 位 X86 称为 __i386__,而不是 __x86__,这可能与您预想的有所不同!

CPU 核心计数:使用 libc 的 sysconf(3)

sysconf(3) 既可以查询 _SC_NPROCESSORS_CONF(系统中的 CPU 核心数),又可以查询 _SC_NPROCESSORS_ONLN(当前在线的 CPU 核心数)。

功能:使用 libc 的 getauxval(3)

自 API 级别 18 开始,Android 的 C 库开始支持 etauxval(3)AT_HWCAPAT_HWCAP2 参数会返回列出特定 CPU 功能的位掩码。请参阅 NDK 中的各种 hwcap.h 头文件以获取要进行比较的常量,如用于 arm64 SHA512 指令的 HWCAP_SHA512,或用于 arm Thumb 整数除法指令的 HWCAP_IDIVT

Google cpu_features 库

AT_HWCAP 的一个问题是有时设备会出错。例如,一些旧设备宣称拥有整数除法指令,但实际上并没有。

Google 的 cpu_features 库凭借其对特定 SoC 的了解(通过解析 /proc/cpuinfo 掌握相应的 SoC),解决了此类问题。

另一个解决方案是为 SIGILL 安装信号处理程序,然后直接尝试执行相关指令。例如,BoringSSL/OpenSSL 使用的就是这种方法。

NDK cpufeatures 库

NDK 提供了一个名为 cpufeatures 的小型库,其功能类似于 getauxval(3),但它也可用于 API 级别 18 之前的版本。与其他 cpu_features 库不同,它对特定 SoC 并无额外的了解。

NDK cpufeatures API

uint64_t android_getCpuFeatures();

返回一组位标记,每个标记代表一个 CPU 系列特定的功能。本部分其余内容介绍了各个系列的功能。

32 位 ARM CPU 系列

以下标记适用于 32 位 ARM CPU 系列:

ANDROID_CPU_ARM_FEATURE_VFPv2

表示设备的 CPU 支持 VFPv2 指令集。大多数 ARMv6 CPU 都支持此指令集。

ANDROID_CPU_ARM_FEATURE_ARMv7

表示设备的 CPU 支持 armeabi-v7a ABI 所支持的 ARMv7-A 指令集。此指令集同时支持 Thumb-2 和 VFPv3-D16 指令。此返回值还表示支持 VFPv3 硬件 FPU 扩展指令集。

ANDROID_CPU_ARM_FEATURE_VFPv3

表示设备的 CPU 支持 VFPv3 硬件 FPU 扩展指令集。

此值等同于 VFPv3-D16 指令集,后者只提供 16 个硬件双精度 FP 寄存器。

ANDROID_CPU_ARM_FEATURE_VFP_D32

表示设备的 CPU 支持 32 个(而不是 16 个)硬件双精度 FP 寄存器。即使有 32 个硬件双精度 FP 寄存器,也只有 32 个单精度寄存器映射至同一寄存器组。

ANDROID_CPU_ARM_FEATURE_NEON

表示设备的 CPU 支持 ARM Advanced SIMD (NEON) 向量扩展指令集。请注意,ARM 要求这些 CPU 也要实现 VFPv3-D32,VFPv3-D32 提供 32 个硬件 FP 寄存器(与 NEON 单元共享)。

ANDROID_CPU_ARM_FEATURE_VFP_FP16

表示设备的 CPU 支持在 16 位寄存器上执行浮点运算的指令。该功能是 VFPv4 规范的一部分。

ANDROID_CPU_ARM_FEATURE_VFP_FMA

表示设备的 CPU 支持 VFP 指令集的融合乘积累加扩展指令集。它也是 VFPv4 规范的一部分。

ANDROID_CPU_ARM_FEATURE_NEON_FMA

表示设备的 CPU 支持 NEON 指令集的融合乘积累加扩展指令集。它也是 VFPv4 规范的一部分。

ANDROID_CPU_ARM_FEATURE_IDIV_ARM

表示设备的 CPU 在 ARM 模式下支持整数除法。仅适用于更高型号的 CPU,例如 Cortex-A15。

ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

学习宝典

对我们开发者来说,一定要打好基础,随时准备战斗。不论寒冬是否到来,都要把自己的技术做精做深。虽然目前移动端的招聘量确实变少了,但中高端的职位还是很多的,这说明行业只是变得成熟规范起来了。竞争越激烈,产品质量与留存就变得更加重要,我们进入了技术赋能业务的时代。

不论遇到什么困难,都不应该成为我们放弃的理由!

很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,对此我针对Android程序员,我这边给大家整理了一套学习宝典!包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!

Android学习PDF+架构视频+面试文档+源码笔记

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

【算法合集】

【延伸Android必备知识点】

学了一段时间感觉没有方向感,不知道该从那里入手去学习,对此我针对Android程序员,我这边给大家整理了一套学习宝典!包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!

Android学习PDF+架构视频+面试文档+源码笔记

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

[外链图片转存中…(img-QI1DSiZR-1711190740147)]

【算法合集】

[外链图片转存中…(img-WOPgsgPj-1711190740147)]

【延伸Android必备知识点】

[外链图片转存中…(img-YZ0selAD-1711190740148)]

【Android部分高级架构视频学习资源】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值