#2023盲盒+码# 通过案例介绍如何使用AOT 原创

zhushangyuan_
发布于 2023-9-16 17:36
浏览
0收藏

【本文正在参加 2023「盲盒」+码有奖征文活动】,活动链接 https://ost.51cto.com/posts/25284

通过案例介绍如何使用AOT

工程准备

  1. 打开 ArkTS 工程,同步完成。

  2. 将工程编译模式调整为 release,并关闭混淆功能。

    • 将工程编译模式调整为 release

    通过build窗口进行编译构建时,默认Build Hap(s)为 debug 编译模式,Build App(s)为 release 编译模式。

    开发者也可以自主选择编译模式为 debug 或 release。

    通过 DevEco Studio 中下图方式,选择调整Build Hap(s)为 release 编译模式。

    #2023盲盒+码# 通过案例介绍如何使用AOT-开源基础软件社区

    • 关闭混淆功能

      在模块级 build-profile.json5 文件中,配置 buildOption 内的字段。

      {  
        "apiType": 'stageMode',  
        "buildOption": {
          "arkOptions": {
            "apPath": "./modules.ap",
            "obfuscation": {
              "ruleOptions": {
                "enable": false
              }
            }
          },  
        ...  
      }
      
  3. 获取 ap 文件:

    a. 打开生成 ap 文件的开关:

    hdc shell param set ark.profile true
    

    b. 将步骤2中release 模式打包出 HAP 运行在真机上,在需要优化的场景进行操作,从而记录高频操作。

    c. 操作结束后,真机里记录的 ap 文件即可放入应用 AOT 编译使用的目录,通过命令行来获取 ap 文件:

     hdc file recv /data/local/ark-profile/100/{bundle_name}/modules.ap {apPath} 
    
    • {bundle_name}: 表示包名。
    • {apPath}: 表示 buildOption 设置的 apPath 参数对应的路径。

    d. 若设备不再需要获取 ap 文件,可以通过下面两个方法关闭:

    • hdc shell param set ark.profile false
    • 设备重启

    应用代码变化或常用操作变化时,建议重复以上步骤更新 ap 文件。

  4. 从真机中获取 ap 文件,将 ap 文件放入第2步中指定的apPath路径。

  5. 开启端侧安装时编译后,再次启动 release 模式进行编译,并安装。

    hdc shell param set persist.bm.install.arkopt partial
    
  6. 在等待应用安装,且端侧编译优化完成后,应用运行性能即可得到相应的提升。

    可以通过如下方式确认端侧编译是否结束

    • 确认端侧编译过程是否结束

      可通过下面命令,观察 ark_aot_compiler是否退出,退出即表示端侧编译结束。

      hdc shell "ps -ef | grep aot"
      
    • 确认端侧编译文件是否生成

      可通过确认端侧 /data/local/ark-cache/{bundleName}路径下是否有an/ai文件,确认端侧编译是否完成

案例实践

场景介绍

本文案例基于业界编程语言Benchmarks Game中提出的模拟N体问题,编写了类木星体轨道计算程序的ArkTS实现。

实现方式

轨道计算作为一个计算密集型程序,会大量占用系统资源计算能力的任务,需要长时间运行,这段时间会阻塞线程其它事件的处理,不适宜放在主线程进行。

所以,本文案例基于多线程并发机制,以提高CPU利用率,提升应用程序响应速度。关于多线程的实践,可以参考文档OpenHarmony应用多线程能力实践

针对500万次时间推移的轨道计算,任务不需要长时间(>3分钟)占据后台线程,且是一个个独立的任务时,所以使用TaskPool开启多线程实现:

/**
 * 使用TaskPool开启子线程,执行轨道计算任务
 * @param totalTimeSteps 时间推移量
 */
export function computeNBodyByTaskPool(totalTimeSteps: number): void {
  Logger.info(TAG, "computeNBodyByTaskPool: start executing")
  let task: taskpool.Task = new taskpool.Task(computeTask, totalTimeSteps);
  try {
    Logger.info(TAG, 'computeNBodyByTaskPool: start calculating...')
    // 向taskpool线程池派发子线程任务
    taskpool.execute(task, taskpool.Priority.HIGH).then((res: number) => {
      Logger.info(TAG, 'computeNBodyByTaskPool: executed successfully, total time costed = ' + res + ' ms.')
      AppStorage.set<String>('timeCost', 'Total time costed = ' + res + ' ms.')
    })
  } catch (err) {
    Logger.error(TAG, "computeNBodyByTaskPool: execute failed, " + (err as BusinessError).toString())
  }
  Logger.info(TAG, "computeNBodyByTaskPool: finish executing")
}

而针对5000万次时间推移的轨道计算,任务相对需要较长长时间,所以使用Worker开启多线程实现:

/**
 * 使用Worker开启子线程,执行轨道计算任务
 * @param totalTimeSteps 时间推移量
 */
export function computeNBodyByWorker(totalTimeSteps: number): void {
  Logger.info(TAG, "computeNBodyByWorker: start executing")
  let workerInstance = new worker.ThreadWorker("entry/ets/workers/CalculateWorker.ts");
  // 设置如何处理,来自worker线程的消息
  workerInstance.onmessage = function (e: MessageEvents) {
    let data = e.data;
    Logger.info(TAG, 'computeNBodyByWorker: executed successfully, total time costed = ' + data.result + ' ms.')
    AppStorage.set<String>('timeCost', 'Total time costed = ' + data.result + ' ms.');
  }
  // 设置由主线程向worker线程发送什么消息
  workerInstance.postMessage({'timeSteps': totalTimeSteps});
}

被子线程执行的计算任务如下:

/**
 * 运行天体轨道计算程序
 * @param totalTimeSteps 时间推移量
 * @returns 计算时间
 */
@Concurrent
export function computeTask(totalTimeSteps: number): number {
  let start: number = new Date().getTime();
  // 建立孤立系统的动量守恒
  offsetMomentum();
  Logger.info(TAG_IN_TASK, energy().toFixed(9));
  // 更新天体在按指定的时间变化后的位置信息
  for (let i: number = 0; i < totalTimeSteps; i++) {
    advance(0.01);
  }
  // 判断系统计算前后机械能守恒
  Logger.info(TAG_IN_TASK, energy().toFixed(9));
  let end: number = new Date().getTime();
  return end - start;
}

使用限制

  • 本文重点介绍Target AOT模式,仅支持 API 10 及以上版本 Stage 模型的 ArkTS 工程。

  • 目前仅 HAP 和 HSP 支持该功能。

  • Node.js 需要 14.19.1 以上版本。

  • 仅支持在 64 位 ROM 上运行。

  • 不支持混淆,需要关闭混淆功能。

参考资料

开启AOT编译模式-编译构建-DevEco Studio使用指南

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
标签
收藏
回复
举报
回复
    相关推荐