java - 我可以从 Dalvik 和 Android 工具链中获得哪些优化?

标签 java android optimization dalvik

我正在开发一个高性能的 Android 应用程序(一个游戏),虽然我首先尝试编写代码以提高可读性,但我喜欢在脑海中保留一个幕后发生的事情的画面。使用 C++,我对编译器将为我做什么和不做什么有了相当好的直觉。我正在尝试为 Java/Android 做同样的事情。

因此提出了这个问题。我在网上几乎找不到关于这个话题的信息。 Java 编译器、Dalvik 转换器 (dx) 和/或 JITter(在 Android 2.2+ 上)会执行如下优化吗?

  • 方法内联。在什么条件下? private 方法总是可以安全地内联;这会完成吗? public final 方法呢?其他类对象的方法? 静态方法?如果编译器可以轻松推断出对象的运行时类型怎么办?我应该尽可能将方法声明为 finalstatic 吗?

  • 通用子表达式消除。例如,如果我访问 someObject.someField 两次,查找是否只进行一次?如果是对 getter 的调用呢?如果我两次使用某个算术表达式怎么办?它只会被评估一次吗?如果我使用某个表达式的结果(我知道它的值不会改变)作为 for 循环的上限怎么办?

  • 对数组查找进行边界检查。工具链会在某些情况下消除这种情况,例如典型的 for 循环吗?

  • 值内联。对某些 public static final int 的访问是否总是被内联?即使他们在另一个类(class)?即使它们在另一个包中?

  • 分支预测。这是一个多大的问题?分支对典型 Android 设备的性能影响很大吗?

  • 简单的算术。 someInt * 2 会被 someInt << 1 取代吗?

等等……

最佳答案

我是 Ben,他是负责 JIT @ Google 的工程师之一。当 Bill 和我开始这个项目时,目标是尽快交付一个有效的 JIT,对资源争用的影响最小(例如内存占用、CPU 被编译器线程劫持),以便它可以在低端设备上运行出色地。因此,我们使用了一个非常原始的基于轨迹的模型。也就是说,传递给 JIT 编译器的编译实体是一个基本 block ,有时短到一条指令。这样的跟踪将在运行时通过一种称为链接的技术拼接在一起,这样解释器和代码缓存查找就不会经常被调用。在某种程度上,加速的主要来源是消除了频繁执行的代码路径上重复的解释器解析开销。

也就是说,我们确实使用 Froyo JIT 实现了很多本地优化:

  • 寄存器分配(v5te 目标为 8 个寄存器,因为 JIT 生成 Thumb 代码/v7 为 16 个寄存器)
  • 调度(例如,Dalvik 寄存器的冗余 ld/st 消除、负载提升、存储下沉)
  • 冗余空检查消除(如果可以在基本 block 中找到这种冗余)。
  • 简单计数循环的循环形成和优化(即循环体中没有侧导出)。对于这样的循环,优化了基于扩展归纳变量的数组访问,以便仅在循环序言中执行空值和范围检查。
  • 每个虚拟调用站点有一个条目内联缓存,并在运行时进行动态修补。
  • 窥孔优化,例如 mul/div 的文字操作数的功耗降低。

在 Gingerbread 中,我们为 getter/setter 添加了简单的内联。由于底层的 JIT 前端仍然是简单的基于跟踪的,如果被调用者在那里有分支,它将不会被内联。但是实现了内联缓存机制,因此可以毫无问题地内联虚拟 getter/setter。

我们目前正在努力将编译范围扩大到超越简单跟踪的范围,以便编译器具有更大的代码分析和优化窗口。敬请期待。

关于java - 我可以从 Dalvik 和 Android 工具链中获得哪些优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4912695/

相关文章:

java - 如何将 created_time 字段值从 Android Studio 中的 Instagram 媒体对象转换为日期

java - 具有无限滚动优化的 GridView

python - 一旦我们的数据库变得太慢,我该如何创建按需报告?

java - 可打包输入流

java - 向 Boomi 中没有的日期字符串添加偏移量 - Java/"Groovy"脚本映射函数

android - 等到 GPS 启用后再获取 FusedLocationAPI 中的纬度和经度值

performance - OCaml 优化技术

java - 如何模拟延迟?

java - 将 iterable 转换为 RDD

android - 在 Android 上按下 googleMap Marker 时,右下角会出现 2 个按钮,我可以禁用它们吗?