NDK开发性能提升

xiaoeryu Lv5

初步了解以下NDK开发对性能的提升,包括dex2oat的处理、函数运行在解释模式、ART模式、JNI模式的性能差别,以及数据类型的转换。

NDK开发的优缺点

什么是ART模式

dex2oat虽然提升了性能,但是对手机的存储空间、性能、耗电量提出了更高的要求(因为要把几乎所有的函数都要编译一遍),所以从Android7.0开始换为了ART的运作方式

所以java函数在Android7.0之后可能运行在三种模式下:

OAT文件分析

Google提供了一个[oatdump](oatdump/oatdump.cc - platform/art - Git at Google (googlesource.com) )工具来反编译oat文件

新建一个native C++项目来测试对oat文件反编译,分析文件结构

在MainActivity.java中写一个简单函数编译一下,安装到手机上

这里测试项目的SDK最好使用Android5.0以下的不然编译出来的dex太多找起来麻烦

    public int java_add(int num){
        int k = 0;
        for (int i = 0; i < num; i++) {
            k += i;
        }
        return k;
    }
  • 找到生成的odex以及vdex文件

    .vdex:其中包含 APK 的未压缩 DEX 代码,以及一些旨在加快验证速度的元数据。

    .odex:其中包含 APK 中已经过 AOT 编译的方法代码。

  • 将这两个文件拷贝到sdcard/目录下,然后pull下来

  • vdex有自己的文件头,在后面也有原本dex的文件头

删除vdex的文件头之后,就可以直接用dex的模板来解析dex 文件

  • 将删除vdex文件头的文件复制一份为dex文件cp .\base.vdex base.dex

用GDA可以打开(jadx打开失败)

  • 解析后可以看到我们之前写的java_add
接下来再看一下odex

使用系统自带的oatdump工具反编译一下odex文件,顺便将其pull下来查看一下

atdump --oat-file=base.odex >>/sdcard/oatdump01.txt

  • 从结果可以看到oatdump成功的将oat文件反编译为了smail指令
  • 汇编代码没有生成是因为Android7.0之后的ART不会直接把所有函数都执行dex2oat,它会在运行一段时间之后才会编译为汇编代码。

简单测试一下函数的ART模式下和JNI模式下的运行速度差别有多大

        int k = 0;
        for (int i = 0; i < num; i++) {
            k += i;
        }
        return k;
  • 从运行一百万次的结果来看其实差别不是很大,表明java函数在执行了一定次数后迅速的从解释模式切换到了ART模式

Java&Native数据类型对比

Java中有8种基本数据类型:

引用数据类型:

数组引用类型:

接下来写一些demo来测试类型处理

String和jstring的交换

        String resultString = testjstringapis("Hello from java");
        Log.i("xiaoeryu", "result: " + resultString);
extern "C"
JNIEXPORT jstring JNICALL
Java_com_xiaoeryu_performancetest01_MainActivity_testjstringapis(JNIEnv *env, jobject thiz,
                                                                 jstring content) {
    // TODO: implement testjstringapis()
    const char* a = env->GetStringUTFChars(content, nullptr);
    jint jstring_size = env->GetStringUTFLength(content);
    if (a != nullptr){
        __android_log_print(ANDROID_LOG_INFO, "testjstring", "char content: %s, size: %d", a, jstring_size);
    }
    jstring result = env->NewStringUTF("Hello from jni");
    return result;
}

result

  • 标题: NDK开发性能提升
  • 作者: xiaoeryu
  • 创建于 : 2023-10-06 12:05:11
  • 更新于 : 2023-10-06 12:26:59
  • 链接: https://github.com/xiaoeryu/2023/10/06/NDK开发性能提升/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论